ARM: OMAP2+: gpmc: get number of useable GPMC chip-selects via DT
This patch enables usage of DT property 'gpmc,num-cs' as already documented in Documentation/devicetree/bindings/bus/ti-gpmc.txt Though GPMC hardware supports upto 8 chip-selects, but all chip-selects may not be available for use because: - chip-select pin may not be bonded out at SoC device boundary. - chip-select pin-mux may conflict with other pins usage. - board level constrains. gpmc,num-cs allows user to configure maximum number of GPMC chip-selects available for use on any given platform. This ensures: - GPMC child nodes having chip-selects within allowed range are only probed. - And un-used GPMC chip-selects remain blocked.(may be for security reasons). Signed-off-by: Gupta, Pekon <pekon@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
This commit is contained in:
parent
f40739faba
commit
f34f37160c
1 changed files with 29 additions and 9 deletions
|
@ -155,6 +155,7 @@ static struct resource gpmc_cs_mem[GPMC_CS_NUM];
|
||||||
static DEFINE_SPINLOCK(gpmc_mem_lock);
|
static DEFINE_SPINLOCK(gpmc_mem_lock);
|
||||||
/* Define chip-selects as reserved by default until probe completes */
|
/* Define chip-selects as reserved by default until probe completes */
|
||||||
static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1);
|
static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1);
|
||||||
|
static unsigned int gpmc_cs_num = GPMC_CS_NUM;
|
||||||
static unsigned int gpmc_nr_waitpins;
|
static unsigned int gpmc_nr_waitpins;
|
||||||
static struct device *gpmc_dev;
|
static struct device *gpmc_dev;
|
||||||
static int gpmc_irq;
|
static int gpmc_irq;
|
||||||
|
@ -521,8 +522,10 @@ static int gpmc_cs_remap(int cs, u32 base)
|
||||||
int ret;
|
int ret;
|
||||||
u32 old_base, size;
|
u32 old_base, size;
|
||||||
|
|
||||||
if (cs > GPMC_CS_NUM)
|
if (cs > gpmc_cs_num) {
|
||||||
|
pr_err("%s: requested chip-select is disabled\n", __func__);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
}
|
||||||
gpmc_cs_get_memconf(cs, &old_base, &size);
|
gpmc_cs_get_memconf(cs, &old_base, &size);
|
||||||
if (base == old_base)
|
if (base == old_base)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -545,9 +548,10 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
|
||||||
struct resource *res = &gpmc_cs_mem[cs];
|
struct resource *res = &gpmc_cs_mem[cs];
|
||||||
int r = -1;
|
int r = -1;
|
||||||
|
|
||||||
if (cs > GPMC_CS_NUM)
|
if (cs > gpmc_cs_num) {
|
||||||
|
pr_err("%s: requested chip-select is disabled\n", __func__);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
}
|
||||||
size = gpmc_mem_align(size);
|
size = gpmc_mem_align(size);
|
||||||
if (size > (1 << GPMC_SECTION_SHIFT))
|
if (size > (1 << GPMC_SECTION_SHIFT))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -582,7 +586,7 @@ EXPORT_SYMBOL(gpmc_cs_request);
|
||||||
void gpmc_cs_free(int cs)
|
void gpmc_cs_free(int cs)
|
||||||
{
|
{
|
||||||
spin_lock(&gpmc_mem_lock);
|
spin_lock(&gpmc_mem_lock);
|
||||||
if (cs >= GPMC_CS_NUM || cs < 0 || !gpmc_cs_reserved(cs)) {
|
if (cs >= gpmc_cs_num || cs < 0 || !gpmc_cs_reserved(cs)) {
|
||||||
printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
|
printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
|
||||||
BUG();
|
BUG();
|
||||||
spin_unlock(&gpmc_mem_lock);
|
spin_unlock(&gpmc_mem_lock);
|
||||||
|
@ -777,7 +781,7 @@ static void gpmc_mem_exit(void)
|
||||||
{
|
{
|
||||||
int cs;
|
int cs;
|
||||||
|
|
||||||
for (cs = 0; cs < GPMC_CS_NUM; cs++) {
|
for (cs = 0; cs < gpmc_cs_num; cs++) {
|
||||||
if (!gpmc_cs_mem_enabled(cs))
|
if (!gpmc_cs_mem_enabled(cs))
|
||||||
continue;
|
continue;
|
||||||
gpmc_cs_delete_mem(cs);
|
gpmc_cs_delete_mem(cs);
|
||||||
|
@ -798,7 +802,7 @@ static void gpmc_mem_init(void)
|
||||||
gpmc_mem_root.end = GPMC_MEM_END;
|
gpmc_mem_root.end = GPMC_MEM_END;
|
||||||
|
|
||||||
/* Reserve all regions that has been set up by bootloader */
|
/* Reserve all regions that has been set up by bootloader */
|
||||||
for (cs = 0; cs < GPMC_CS_NUM; cs++) {
|
for (cs = 0; cs < gpmc_cs_num; cs++) {
|
||||||
u32 base, size;
|
u32 base, size;
|
||||||
|
|
||||||
if (!gpmc_cs_mem_enabled(cs))
|
if (!gpmc_cs_mem_enabled(cs))
|
||||||
|
@ -1526,6 +1530,20 @@ static int gpmc_probe_dt(struct platform_device *pdev)
|
||||||
if (!of_id)
|
if (!of_id)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-cs",
|
||||||
|
&gpmc_cs_num);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("%s: number of chip-selects not defined\n", __func__);
|
||||||
|
return ret;
|
||||||
|
} else if (gpmc_cs_num < 1) {
|
||||||
|
pr_err("%s: all chip-selects are disabled\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
} else if (gpmc_cs_num > GPMC_CS_NUM) {
|
||||||
|
pr_err("%s: number of supported chip-selects cannot be > %d\n",
|
||||||
|
__func__, GPMC_CS_NUM);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-waitpins",
|
ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-waitpins",
|
||||||
&gpmc_nr_waitpins);
|
&gpmc_nr_waitpins);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -1623,8 +1641,10 @@ static int gpmc_probe(struct platform_device *pdev)
|
||||||
/* Now the GPMC is initialised, unreserve the chip-selects */
|
/* Now the GPMC is initialised, unreserve the chip-selects */
|
||||||
gpmc_cs_map = 0;
|
gpmc_cs_map = 0;
|
||||||
|
|
||||||
if (!pdev->dev.of_node)
|
if (!pdev->dev.of_node) {
|
||||||
|
gpmc_cs_num = GPMC_CS_NUM;
|
||||||
gpmc_nr_waitpins = GPMC_NR_WAITPINS;
|
gpmc_nr_waitpins = GPMC_NR_WAITPINS;
|
||||||
|
}
|
||||||
|
|
||||||
rc = gpmc_probe_dt(pdev);
|
rc = gpmc_probe_dt(pdev);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
|
@ -1728,7 +1748,7 @@ void omap3_gpmc_save_context(void)
|
||||||
gpmc_context.prefetch_config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
|
gpmc_context.prefetch_config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
|
||||||
gpmc_context.prefetch_config2 = gpmc_read_reg(GPMC_PREFETCH_CONFIG2);
|
gpmc_context.prefetch_config2 = gpmc_read_reg(GPMC_PREFETCH_CONFIG2);
|
||||||
gpmc_context.prefetch_control = gpmc_read_reg(GPMC_PREFETCH_CONTROL);
|
gpmc_context.prefetch_control = gpmc_read_reg(GPMC_PREFETCH_CONTROL);
|
||||||
for (i = 0; i < GPMC_CS_NUM; i++) {
|
for (i = 0; i < gpmc_cs_num; i++) {
|
||||||
gpmc_context.cs_context[i].is_valid = gpmc_cs_mem_enabled(i);
|
gpmc_context.cs_context[i].is_valid = gpmc_cs_mem_enabled(i);
|
||||||
if (gpmc_context.cs_context[i].is_valid) {
|
if (gpmc_context.cs_context[i].is_valid) {
|
||||||
gpmc_context.cs_context[i].config1 =
|
gpmc_context.cs_context[i].config1 =
|
||||||
|
@ -1760,7 +1780,7 @@ void omap3_gpmc_restore_context(void)
|
||||||
gpmc_write_reg(GPMC_PREFETCH_CONFIG1, gpmc_context.prefetch_config1);
|
gpmc_write_reg(GPMC_PREFETCH_CONFIG1, gpmc_context.prefetch_config1);
|
||||||
gpmc_write_reg(GPMC_PREFETCH_CONFIG2, gpmc_context.prefetch_config2);
|
gpmc_write_reg(GPMC_PREFETCH_CONFIG2, gpmc_context.prefetch_config2);
|
||||||
gpmc_write_reg(GPMC_PREFETCH_CONTROL, gpmc_context.prefetch_control);
|
gpmc_write_reg(GPMC_PREFETCH_CONTROL, gpmc_context.prefetch_control);
|
||||||
for (i = 0; i < GPMC_CS_NUM; i++) {
|
for (i = 0; i < gpmc_cs_num; i++) {
|
||||||
if (gpmc_context.cs_context[i].is_valid) {
|
if (gpmc_context.cs_context[i].is_valid) {
|
||||||
gpmc_cs_write_reg(i, GPMC_CS_CONFIG1,
|
gpmc_cs_write_reg(i, GPMC_CS_CONFIG1,
|
||||||
gpmc_context.cs_context[i].config1);
|
gpmc_context.cs_context[i].config1);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue