Home | History | Annotate | Download | only in gpio
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright (C) 2009
      4  * Guennadi Liakhovetski, DENX Software Engineering, <lg (at) denx.de>
      5  *
      6  * Copyright (C) 2011
      7  * Stefano Babic, DENX Software Engineering, <sbabic (at) denx.de>
      8  */
      9 #include <common.h>
     10 #include <errno.h>
     11 #include <dm.h>
     12 #include <malloc.h>
     13 #include <asm/arch/imx-regs.h>
     14 #include <asm/gpio.h>
     15 #include <asm/io.h>
     16 
     17 enum mxc_gpio_direction {
     18 	MXC_GPIO_DIRECTION_IN,
     19 	MXC_GPIO_DIRECTION_OUT,
     20 };
     21 
     22 #define GPIO_PER_BANK			32
     23 
     24 struct mxc_gpio_plat {
     25 	int bank_index;
     26 	struct gpio_regs *regs;
     27 };
     28 
     29 struct mxc_bank_info {
     30 	struct gpio_regs *regs;
     31 };
     32 
     33 #ifndef CONFIG_DM_GPIO
     34 #define GPIO_TO_PORT(n)		(n / 32)
     35 
     36 /* GPIO port description */
     37 static unsigned long gpio_ports[] = {
     38 	[0] = GPIO1_BASE_ADDR,
     39 	[1] = GPIO2_BASE_ADDR,
     40 	[2] = GPIO3_BASE_ADDR,
     41 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
     42 		defined(CONFIG_MX53) || defined(CONFIG_MX6) || \
     43 		defined(CONFIG_MX7) || defined(CONFIG_MX8M)
     44 	[3] = GPIO4_BASE_ADDR,
     45 #endif
     46 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) || \
     47 		defined(CONFIG_MX7) || defined(CONFIG_MX8M)
     48 	[4] = GPIO5_BASE_ADDR,
     49 #if !(defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL) || defined(CONFIG_MX8M))
     50 	[5] = GPIO6_BASE_ADDR,
     51 #endif
     52 #endif
     53 #if defined(CONFIG_MX53) || defined(CONFIG_MX6) || defined(CONFIG_MX7)
     54 #if !(defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL))
     55 	[6] = GPIO7_BASE_ADDR,
     56 #endif
     57 #endif
     58 };
     59 
     60 static int mxc_gpio_direction(unsigned int gpio,
     61 	enum mxc_gpio_direction direction)
     62 {
     63 	unsigned int port = GPIO_TO_PORT(gpio);
     64 	struct gpio_regs *regs;
     65 	u32 l;
     66 
     67 	if (port >= ARRAY_SIZE(gpio_ports))
     68 		return -1;
     69 
     70 	gpio &= 0x1f;
     71 
     72 	regs = (struct gpio_regs *)gpio_ports[port];
     73 
     74 	l = readl(&regs->gpio_dir);
     75 
     76 	switch (direction) {
     77 	case MXC_GPIO_DIRECTION_OUT:
     78 		l |= 1 << gpio;
     79 		break;
     80 	case MXC_GPIO_DIRECTION_IN:
     81 		l &= ~(1 << gpio);
     82 	}
     83 	writel(l, &regs->gpio_dir);
     84 
     85 	return 0;
     86 }
     87 
     88 int gpio_set_value(unsigned gpio, int value)
     89 {
     90 	unsigned int port = GPIO_TO_PORT(gpio);
     91 	struct gpio_regs *regs;
     92 	u32 l;
     93 
     94 	if (port >= ARRAY_SIZE(gpio_ports))
     95 		return -1;
     96 
     97 	gpio &= 0x1f;
     98 
     99 	regs = (struct gpio_regs *)gpio_ports[port];
    100 
    101 	l = readl(&regs->gpio_dr);
    102 	if (value)
    103 		l |= 1 << gpio;
    104 	else
    105 		l &= ~(1 << gpio);
    106 	writel(l, &regs->gpio_dr);
    107 
    108 	return 0;
    109 }
    110 
    111 int gpio_get_value(unsigned gpio)
    112 {
    113 	unsigned int port = GPIO_TO_PORT(gpio);
    114 	struct gpio_regs *regs;
    115 	u32 val;
    116 
    117 	if (port >= ARRAY_SIZE(gpio_ports))
    118 		return -1;
    119 
    120 	gpio &= 0x1f;
    121 
    122 	regs = (struct gpio_regs *)gpio_ports[port];
    123 
    124 	val = (readl(&regs->gpio_psr) >> gpio) & 0x01;
    125 
    126 	return val;
    127 }
    128 
    129 int gpio_request(unsigned gpio, const char *label)
    130 {
    131 	unsigned int port = GPIO_TO_PORT(gpio);
    132 	if (port >= ARRAY_SIZE(gpio_ports))
    133 		return -1;
    134 	return 0;
    135 }
    136 
    137 int gpio_free(unsigned gpio)
    138 {
    139 	return 0;
    140 }
    141 
    142 int gpio_direction_input(unsigned gpio)
    143 {
    144 	return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN);
    145 }
    146 
    147 int gpio_direction_output(unsigned gpio, int value)
    148 {
    149 	int ret = gpio_set_value(gpio, value);
    150 
    151 	if (ret < 0)
    152 		return ret;
    153 
    154 	return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT);
    155 }
    156 #endif
    157 
    158 #ifdef CONFIG_DM_GPIO
    159 #include <fdtdec.h>
    160 static int mxc_gpio_is_output(struct gpio_regs *regs, int offset)
    161 {
    162 	u32 val;
    163 
    164 	val = readl(&regs->gpio_dir);
    165 
    166 	return val & (1 << offset) ? 1 : 0;
    167 }
    168 
    169 static void mxc_gpio_bank_direction(struct gpio_regs *regs, int offset,
    170 				    enum mxc_gpio_direction direction)
    171 {
    172 	u32 l;
    173 
    174 	l = readl(&regs->gpio_dir);
    175 
    176 	switch (direction) {
    177 	case MXC_GPIO_DIRECTION_OUT:
    178 		l |= 1 << offset;
    179 		break;
    180 	case MXC_GPIO_DIRECTION_IN:
    181 		l &= ~(1 << offset);
    182 	}
    183 	writel(l, &regs->gpio_dir);
    184 }
    185 
    186 static void mxc_gpio_bank_set_value(struct gpio_regs *regs, int offset,
    187 				    int value)
    188 {
    189 	u32 l;
    190 
    191 	l = readl(&regs->gpio_dr);
    192 	if (value)
    193 		l |= 1 << offset;
    194 	else
    195 		l &= ~(1 << offset);
    196 	writel(l, &regs->gpio_dr);
    197 }
    198 
    199 static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset)
    200 {
    201 	return (readl(&regs->gpio_psr) >> offset) & 0x01;
    202 }
    203 
    204 /* set GPIO pin 'gpio' as an input */
    205 static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset)
    206 {
    207 	struct mxc_bank_info *bank = dev_get_priv(dev);
    208 
    209 	/* Configure GPIO direction as input. */
    210 	mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN);
    211 
    212 	return 0;
    213 }
    214 
    215 /* set GPIO pin 'gpio' as an output, with polarity 'value' */
    216 static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset,
    217 				       int value)
    218 {
    219 	struct mxc_bank_info *bank = dev_get_priv(dev);
    220 
    221 	/* Configure GPIO output value. */
    222 	mxc_gpio_bank_set_value(bank->regs, offset, value);
    223 
    224 	/* Configure GPIO direction as output. */
    225 	mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_OUT);
    226 
    227 	return 0;
    228 }
    229 
    230 /* read GPIO IN value of pin 'gpio' */
    231 static int mxc_gpio_get_value(struct udevice *dev, unsigned offset)
    232 {
    233 	struct mxc_bank_info *bank = dev_get_priv(dev);
    234 
    235 	return mxc_gpio_bank_get_value(bank->regs, offset);
    236 }
    237 
    238 /* write GPIO OUT value to pin 'gpio' */
    239 static int mxc_gpio_set_value(struct udevice *dev, unsigned offset,
    240 				 int value)
    241 {
    242 	struct mxc_bank_info *bank = dev_get_priv(dev);
    243 
    244 	mxc_gpio_bank_set_value(bank->regs, offset, value);
    245 
    246 	return 0;
    247 }
    248 
    249 static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
    250 {
    251 	struct mxc_bank_info *bank = dev_get_priv(dev);
    252 
    253 	/* GPIOF_FUNC is not implemented yet */
    254 	if (mxc_gpio_is_output(bank->regs, offset))
    255 		return GPIOF_OUTPUT;
    256 	else
    257 		return GPIOF_INPUT;
    258 }
    259 
    260 static const struct dm_gpio_ops gpio_mxc_ops = {
    261 	.direction_input	= mxc_gpio_direction_input,
    262 	.direction_output	= mxc_gpio_direction_output,
    263 	.get_value		= mxc_gpio_get_value,
    264 	.set_value		= mxc_gpio_set_value,
    265 	.get_function		= mxc_gpio_get_function,
    266 };
    267 
    268 static int mxc_gpio_probe(struct udevice *dev)
    269 {
    270 	struct mxc_bank_info *bank = dev_get_priv(dev);
    271 	struct mxc_gpio_plat *plat = dev_get_platdata(dev);
    272 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
    273 	int banknum;
    274 	char name[18], *str;
    275 
    276 	banknum = plat->bank_index;
    277 	sprintf(name, "GPIO%d_", banknum + 1);
    278 	str = strdup(name);
    279 	if (!str)
    280 		return -ENOMEM;
    281 	uc_priv->bank_name = str;
    282 	uc_priv->gpio_count = GPIO_PER_BANK;
    283 	bank->regs = plat->regs;
    284 
    285 	return 0;
    286 }
    287 
    288 static int mxc_gpio_bind(struct udevice *dev)
    289 {
    290 	struct mxc_gpio_plat *plat = dev->platdata;
    291 	fdt_addr_t addr;
    292 
    293 	/*
    294 	 * If platdata already exsits, directly return.
    295 	 * Actually only when DT is not supported, platdata
    296 	 * is statically initialized in U_BOOT_DEVICES.Here
    297 	 * will return.
    298 	 */
    299 	if (plat)
    300 		return 0;
    301 
    302 	addr = devfdt_get_addr(dev);
    303 	if (addr == FDT_ADDR_T_NONE)
    304 		return -EINVAL;
    305 
    306 	/*
    307 	 * TODO:
    308 	 * When every board is converted to driver model and DT is supported,
    309 	 * this can be done by auto-alloc feature, but not using calloc
    310 	 * to alloc memory for platdata.
    311 	 *
    312 	 * For example mxc_plat below uses platform data rather than device
    313 	 * tree.
    314 	 *
    315 	 * NOTE: DO NOT COPY this code if you are using device tree.
    316 	 */
    317 	plat = calloc(1, sizeof(*plat));
    318 	if (!plat)
    319 		return -ENOMEM;
    320 
    321 	plat->regs = (struct gpio_regs *)addr;
    322 	plat->bank_index = dev->req_seq;
    323 	dev->platdata = plat;
    324 
    325 	return 0;
    326 }
    327 
    328 static const struct udevice_id mxc_gpio_ids[] = {
    329 	{ .compatible = "fsl,imx35-gpio" },
    330 	{ }
    331 };
    332 
    333 U_BOOT_DRIVER(gpio_mxc) = {
    334 	.name	= "gpio_mxc",
    335 	.id	= UCLASS_GPIO,
    336 	.ops	= &gpio_mxc_ops,
    337 	.probe	= mxc_gpio_probe,
    338 	.priv_auto_alloc_size = sizeof(struct mxc_bank_info),
    339 	.of_match = mxc_gpio_ids,
    340 	.bind	= mxc_gpio_bind,
    341 };
    342 
    343 #if !CONFIG_IS_ENABLED(OF_CONTROL)
    344 static const struct mxc_gpio_plat mxc_plat[] = {
    345 	{ 0, (struct gpio_regs *)GPIO1_BASE_ADDR },
    346 	{ 1, (struct gpio_regs *)GPIO2_BASE_ADDR },
    347 	{ 2, (struct gpio_regs *)GPIO3_BASE_ADDR },
    348 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
    349 		defined(CONFIG_MX53) || defined(CONFIG_MX6) || \
    350 		defined(CONFIG_MX8M)
    351 	{ 3, (struct gpio_regs *)GPIO4_BASE_ADDR },
    352 #endif
    353 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) || \
    354 		defined(CONFIG_MX8M)
    355 	{ 4, (struct gpio_regs *)GPIO5_BASE_ADDR },
    356 #ifndef CONFIG_MX8M
    357 	{ 5, (struct gpio_regs *)GPIO6_BASE_ADDR },
    358 #endif
    359 #endif
    360 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
    361 	{ 6, (struct gpio_regs *)GPIO7_BASE_ADDR },
    362 #endif
    363 };
    364 
    365 U_BOOT_DEVICES(mxc_gpios) = {
    366 	{ "gpio_mxc", &mxc_plat[0] },
    367 	{ "gpio_mxc", &mxc_plat[1] },
    368 	{ "gpio_mxc", &mxc_plat[2] },
    369 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
    370 		defined(CONFIG_MX53) || defined(CONFIG_MX6) || \
    371 		defined(CONFIG_MX8M)
    372 	{ "gpio_mxc", &mxc_plat[3] },
    373 #endif
    374 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) || \
    375 		defined(CONFIG_MX8M)
    376 	{ "gpio_mxc", &mxc_plat[4] },
    377 #ifndef CONFIG_MX8M
    378 	{ "gpio_mxc", &mxc_plat[5] },
    379 #endif
    380 #endif
    381 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
    382 	{ "gpio_mxc", &mxc_plat[6] },
    383 #endif
    384 };
    385 #endif
    386 #endif
    387