[U-Boot] [PATCH v2] dm:gpio:mxc add DT support
Peng Fan
B51431 at freescale.com
Wed Jan 21 03:18:42 CET 2015
Hi, Igor
On 1/20/2015 10:39 PM, Igor Grinberg wrote:
> On 01/20/15 09:15, Peng Fan wrote:
>> This patch add DT support for mxc gpio driver.
>>
>> Include a bank_index entry in platdata. This can avoid using
>> `plat - mxc_plat` to calculate bank number. Also this can simplify code.
> Although, I don't insist, but I would recommend to split the patch into 2:
> the bank_index rework and the DT support addition.
Ok. I can split this in v3 patch.
>
>> There are two places still using CONFIG_OF_CONTROL macro, just to
>> shrink code size if only support DM but not support DT.
>> 1. The U_BOOT_DEVICES and mxc_plat array are complied out. To DT,
>> platdata is alloced using calloc, so there is no need to use mxc_plat.
>> 2. add a function mxc_get_gpio_addr to get "reg" property if DT support.
>> If no DT, this function just returns NULL.
> I have some comments on this one, please see below...
Reply below.
>
>> The following situations are tested:
>> 1. with DM, without DT
>> 2. with DM and DT
>> 3. without DM
>> Since device tree has not been upstreamed, if want to test this patch.
>> The followings need to be done.
>> + pieces of code does not gpio_request when using gpio_direction_xxx and
>> etc, need to request gpio.
>> + move the gpio settings from board_early_init_f to board_init
>> + define CONFIG_DM ,CONFIG_DM_GPIO and CONFIG_OF_CONTROL
>> + Add device tree file and do related configuration in
>> `make ARCH=arm menuconfig`
>> These will be done in future patches by step.
>>
>> Signed-off-by: Peng Fan <Peng.Fan at freescale.com>
>> ---
>>
>> Changes v2:
>> 1. remove uneccessary #ifdef
>> 2. add more stuff in commit log
>> 3. include a new function mxc_get_gpio_addr to get register base.
>> This function is different for DT and not DT, by `#ifdef`.
>> If using one implementation for DT and not DT, final image will be big.
>> 4. include a new entry in platdata, named bank_index. it can simplify DT
>> support. To no DT, bank_index is static initilized; to DT, bank_index
>> is get from device's req_seq.
>>
>> drivers/gpio/mxc_gpio.c | 89 +++++++++++++++++++++++++++++++++++++++----------
>> 1 file changed, 71 insertions(+), 18 deletions(-)
>>
>> diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c
>> index 8bb9e39..5826620 100644
>> --- a/drivers/gpio/mxc_gpio.c
>> +++ b/drivers/gpio/mxc_gpio.c
>> @@ -23,6 +23,7 @@ enum mxc_gpio_direction {
>> #define GPIO_PER_BANK 32
>>
>> struct mxc_gpio_plat {
>> + int bank_index;
>> struct gpio_regs *regs;
>> };
>>
>> @@ -150,6 +151,9 @@ int gpio_direction_output(unsigned gpio, int value)
>> #endif
>>
>> #ifdef CONFIG_DM_GPIO
>> +#include <fdtdec.h>
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> static int mxc_gpio_is_output(struct gpio_regs *regs, int offset)
>> {
>> u32 val;
>> @@ -258,23 +262,6 @@ static const struct dm_gpio_ops gpio_mxc_ops = {
>> .get_function = mxc_gpio_get_function,
>> };
>>
>> -static const struct mxc_gpio_plat mxc_plat[] = {
>> - { (struct gpio_regs *)GPIO1_BASE_ADDR },
>> - { (struct gpio_regs *)GPIO2_BASE_ADDR },
>> - { (struct gpio_regs *)GPIO3_BASE_ADDR },
>> -#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
>> - defined(CONFIG_MX53) || defined(CONFIG_MX6)
>> - { (struct gpio_regs *)GPIO4_BASE_ADDR },
>> -#endif
>> -#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
>> - { (struct gpio_regs *)GPIO5_BASE_ADDR },
>> - { (struct gpio_regs *)GPIO6_BASE_ADDR },
>> -#endif
>> -#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
>> - { (struct gpio_regs *)GPIO7_BASE_ADDR },
>> -#endif
>> -};
>> -
>> static int mxc_gpio_probe(struct udevice *dev)
>> {
>> struct mxc_bank_info *bank = dev_get_priv(dev);
>> @@ -283,7 +270,7 @@ static int mxc_gpio_probe(struct udevice *dev)
>> int banknum;
>> char name[18], *str;
>>
>> - banknum = plat - mxc_plat;
>> + banknum = plat->bank_index;
>> sprintf(name, "GPIO%d_", banknum + 1);
>> str = strdup(name);
>> if (!str)
>> @@ -295,12 +282,77 @@ static int mxc_gpio_probe(struct udevice *dev)
>> return 0;
>> }
>>
>> +#ifdef CONFIG_OF_CONTROL
>> +static struct gpio_regs *mxc_get_gpio_addr(struct udevice *device)
>> +{
>> + fdt_addr_t addr;
>> + addr = fdtdec_get_addr(gd->fdt_blob, device->of_offset, "reg");
>> + if (addr == FDT_ADDR_T_NONE)
>> + return NULL;
>> + else
>> + return (struct gpio_regs *)addr;
>> +}
>> +#else
>> +static struct gpio_regs *mxc_get_gpio_addr(struct udevice *device)
>> +{
>> + return NULL;
>> +}
>> +#endif
> In general, I'm fine with this concept, but I believe we should implement
> a stub for fdtdec_get_addr() function in the fdtdec.h (say just returning
> FDT_ADDR_T_NONE), as otherwise we might end up with multiple drivers
> implementing the same noop callback just to work around a poor fdtdec_*()
> interface.
I tried to implement a stub function in fdtdec.h like this:
__weak fdt_addr_t fdtdec_get_addr_wrap(xxxx)
{
return FDT_ADDR_T_NONE;
}
And in driver code, implement non weak version as following:
#ifdef CONFIG_OF_CONTROL
fdt_addr_t fdtdec_get_addr_wrap(xxxx)
{
..........
}
#endif
But gcc complains about conficting types, since we have a weak
implementation in header file and a strong implementation in c file. If
the weak one is in fdtxx c file, no error, but i thinke this is not a
good idea to put this in fdtxx c file. If we do not want DT, but only
DM, DT code should not be compiled into the final image.
I tried another way, add the following piece code in
driver/core/device.c and function prototype in device.h,
"
#ifdef CONFIG_OF_CONTROL
void *dev_reg_addr(struct udevice *dev)
{
fdt_addr_t addr;
addr = fdtdev_get_addr(gd->fdt_blob, dev->of_offset, "reg");
if (addr == FDT_ADDR_T_NONE)
return NULL;
else
return (void *)addr
}
#else
void *dev_reg_addr(struct udevice *dev)
{
return NULL;
}
#endif
"
I think `#ifdef` is needed here. I think this way is better that put
stub function in fdtdec.h. Using this way, the driver code can just `add
= dev_reg_addr(device)` to get reg address.
Maybe the upper piece code should be put in a new file named
device-util.c in directory device/core but not device.c?
Comments?
>> +
>> +static int mxc_gpio_bind(struct udevice *device)
>> +{
>> + struct mxc_gpio_plat *plat = device->platdata;
>> + struct gpio_regs *regs;
>> +
>> + if (plat)
>> + return 0;
>> +
>> + regs = mxc_get_gpio_addr(device);
>> + if (!regs)
>> + return -ENXIO;
>> +
>> + plat = calloc(1, sizeof(*plat));
>> + if (!plat)
>> + return -ENOMEM;
>> +
>> + plat->regs = regs;
>> + plat->bank_index = device->req_seq;
>> + device->platdata = plat;
>> +
>> + return 0;
>> +}
>> +
>> +static const struct udevice_id mxc_gpio_ids[] = {
>> + { .compatible = "fsl,imx35-gpio" },
>> + { }
>> +};
>> +
>> U_BOOT_DRIVER(gpio_mxc) = {
>> .name = "gpio_mxc",
>> .id = UCLASS_GPIO,
>> .ops = &gpio_mxc_ops,
>> .probe = mxc_gpio_probe,
>> .priv_auto_alloc_size = sizeof(struct mxc_bank_info),
>> + .of_match = mxc_gpio_ids,
>> + .bind = mxc_gpio_bind,
>> +};
>> +
>> +#ifndef CONFIG_OF_CONTROL
>> +static const struct mxc_gpio_plat mxc_plat[] = {
>> + { 0, (struct gpio_regs *)GPIO1_BASE_ADDR },
>> + { 1, (struct gpio_regs *)GPIO2_BASE_ADDR },
>> + { 2, (struct gpio_regs *)GPIO3_BASE_ADDR },
>> +#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
>> + defined(CONFIG_MX53) || defined(CONFIG_MX6)
>> + { 3, (struct gpio_regs *)GPIO4_BASE_ADDR },
>> +#endif
>> +#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
>> + { 4, (struct gpio_regs *)GPIO5_BASE_ADDR },
>> + { 5, (struct gpio_regs *)GPIO6_BASE_ADDR },
>> +#endif
>> +#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
>> + { 6, (struct gpio_regs *)GPIO7_BASE_ADDR },
>> +#endif
>> };
>>
>> U_BOOT_DEVICES(mxc_gpios) = {
>> @@ -320,3 +372,4 @@ U_BOOT_DEVICES(mxc_gpios) = {
>> #endif
>> };
>> #endif
>> +#endif
>>
Regards,
Peng.
More information about the U-Boot
mailing list