cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gpio-mpc5200.c (9143B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * MPC52xx gpio driver
      4 *
      5 * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
      6 */
      7
      8#include <linux/of.h>
      9#include <linux/kernel.h>
     10#include <linux/slab.h>
     11#include <linux/of_gpio.h>
     12#include <linux/io.h>
     13#include <linux/of_platform.h>
     14#include <linux/module.h>
     15
     16#include <asm/mpc52xx.h>
     17#include <sysdev/fsl_soc.h>
     18
     19static DEFINE_SPINLOCK(gpio_lock);
     20
     21struct mpc52xx_gpiochip {
     22	struct of_mm_gpio_chip mmchip;
     23	unsigned int shadow_dvo;
     24	unsigned int shadow_gpioe;
     25	unsigned int shadow_ddr;
     26};
     27
     28/*
     29 * GPIO LIB API implementation for wakeup GPIOs.
     30 *
     31 * There's a maximum of 8 wakeup GPIOs. Which of these are available
     32 * for use depends on your board setup.
     33 *
     34 * 0 -> GPIO_WKUP_7
     35 * 1 -> GPIO_WKUP_6
     36 * 2 -> PSC6_1
     37 * 3 -> PSC6_0
     38 * 4 -> ETH_17
     39 * 5 -> PSC3_9
     40 * 6 -> PSC2_4
     41 * 7 -> PSC1_4
     42 *
     43 */
     44static int mpc52xx_wkup_gpio_get(struct gpio_chip *gc, unsigned int gpio)
     45{
     46	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
     47	struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
     48	unsigned int ret;
     49
     50	ret = (in_8(&regs->wkup_ival) >> (7 - gpio)) & 1;
     51
     52	pr_debug("%s: gpio: %d ret: %d\n", __func__, gpio, ret);
     53
     54	return ret;
     55}
     56
     57static inline void
     58__mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
     59{
     60	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
     61	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
     62	struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
     63
     64	if (val)
     65		chip->shadow_dvo |= 1 << (7 - gpio);
     66	else
     67		chip->shadow_dvo &= ~(1 << (7 - gpio));
     68
     69	out_8(&regs->wkup_dvo, chip->shadow_dvo);
     70}
     71
     72static void
     73mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
     74{
     75	unsigned long flags;
     76
     77	spin_lock_irqsave(&gpio_lock, flags);
     78
     79	__mpc52xx_wkup_gpio_set(gc, gpio, val);
     80
     81	spin_unlock_irqrestore(&gpio_lock, flags);
     82
     83	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
     84}
     85
     86static int mpc52xx_wkup_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
     87{
     88	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
     89	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
     90	struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
     91	unsigned long flags;
     92
     93	spin_lock_irqsave(&gpio_lock, flags);
     94
     95	/* set the direction */
     96	chip->shadow_ddr &= ~(1 << (7 - gpio));
     97	out_8(&regs->wkup_ddr, chip->shadow_ddr);
     98
     99	/* and enable the pin */
    100	chip->shadow_gpioe |= 1 << (7 - gpio);
    101	out_8(&regs->wkup_gpioe, chip->shadow_gpioe);
    102
    103	spin_unlock_irqrestore(&gpio_lock, flags);
    104
    105	return 0;
    106}
    107
    108static int
    109mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
    110{
    111	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
    112	struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
    113	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
    114	unsigned long flags;
    115
    116	spin_lock_irqsave(&gpio_lock, flags);
    117
    118	__mpc52xx_wkup_gpio_set(gc, gpio, val);
    119
    120	/* Then set direction */
    121	chip->shadow_ddr |= 1 << (7 - gpio);
    122	out_8(&regs->wkup_ddr, chip->shadow_ddr);
    123
    124	/* Finally enable the pin */
    125	chip->shadow_gpioe |= 1 << (7 - gpio);
    126	out_8(&regs->wkup_gpioe, chip->shadow_gpioe);
    127
    128	spin_unlock_irqrestore(&gpio_lock, flags);
    129
    130	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
    131
    132	return 0;
    133}
    134
    135static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
    136{
    137	struct mpc52xx_gpiochip *chip;
    138	struct mpc52xx_gpio_wkup __iomem *regs;
    139	struct gpio_chip *gc;
    140	int ret;
    141
    142	chip = devm_kzalloc(&ofdev->dev, sizeof(*chip), GFP_KERNEL);
    143	if (!chip)
    144		return -ENOMEM;
    145
    146	platform_set_drvdata(ofdev, chip);
    147
    148	gc = &chip->mmchip.gc;
    149
    150	gc->ngpio            = 8;
    151	gc->direction_input  = mpc52xx_wkup_gpio_dir_in;
    152	gc->direction_output = mpc52xx_wkup_gpio_dir_out;
    153	gc->get              = mpc52xx_wkup_gpio_get;
    154	gc->set              = mpc52xx_wkup_gpio_set;
    155
    156	ret = of_mm_gpiochip_add_data(ofdev->dev.of_node, &chip->mmchip, chip);
    157	if (ret)
    158		return ret;
    159
    160	regs = chip->mmchip.regs;
    161	chip->shadow_gpioe = in_8(&regs->wkup_gpioe);
    162	chip->shadow_ddr = in_8(&regs->wkup_ddr);
    163	chip->shadow_dvo = in_8(&regs->wkup_dvo);
    164
    165	return 0;
    166}
    167
    168static int mpc52xx_gpiochip_remove(struct platform_device *ofdev)
    169{
    170	struct mpc52xx_gpiochip *chip = platform_get_drvdata(ofdev);
    171
    172	of_mm_gpiochip_remove(&chip->mmchip);
    173
    174	return 0;
    175}
    176
    177static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = {
    178	{ .compatible = "fsl,mpc5200-gpio-wkup", },
    179	{}
    180};
    181
    182static struct platform_driver mpc52xx_wkup_gpiochip_driver = {
    183	.driver = {
    184		.name = "mpc5200-gpio-wkup",
    185		.of_match_table = mpc52xx_wkup_gpiochip_match,
    186	},
    187	.probe = mpc52xx_wkup_gpiochip_probe,
    188	.remove = mpc52xx_gpiochip_remove,
    189};
    190
    191/*
    192 * GPIO LIB API implementation for simple GPIOs
    193 *
    194 * There's a maximum of 32 simple GPIOs. Which of these are available
    195 * for use depends on your board setup.
    196 * The numbering reflects the bit numbering in the port registers:
    197 *
    198 *  0..1  > reserved
    199 *  2..3  > IRDA
    200 *  4..7  > ETHR
    201 *  8..11 > reserved
    202 * 12..15 > USB
    203 * 16..17 > reserved
    204 * 18..23 > PSC3
    205 * 24..27 > PSC2
    206 * 28..31 > PSC1
    207 */
    208static int mpc52xx_simple_gpio_get(struct gpio_chip *gc, unsigned int gpio)
    209{
    210	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
    211	struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
    212	unsigned int ret;
    213
    214	ret = (in_be32(&regs->simple_ival) >> (31 - gpio)) & 1;
    215
    216	return ret;
    217}
    218
    219static inline void
    220__mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
    221{
    222	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
    223	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
    224	struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
    225
    226	if (val)
    227		chip->shadow_dvo |= 1 << (31 - gpio);
    228	else
    229		chip->shadow_dvo &= ~(1 << (31 - gpio));
    230	out_be32(&regs->simple_dvo, chip->shadow_dvo);
    231}
    232
    233static void
    234mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
    235{
    236	unsigned long flags;
    237
    238	spin_lock_irqsave(&gpio_lock, flags);
    239
    240	__mpc52xx_simple_gpio_set(gc, gpio, val);
    241
    242	spin_unlock_irqrestore(&gpio_lock, flags);
    243
    244	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
    245}
    246
    247static int mpc52xx_simple_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
    248{
    249	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
    250	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
    251	struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
    252	unsigned long flags;
    253
    254	spin_lock_irqsave(&gpio_lock, flags);
    255
    256	/* set the direction */
    257	chip->shadow_ddr &= ~(1 << (31 - gpio));
    258	out_be32(&regs->simple_ddr, chip->shadow_ddr);
    259
    260	/* and enable the pin */
    261	chip->shadow_gpioe |= 1 << (31 - gpio);
    262	out_be32(&regs->simple_gpioe, chip->shadow_gpioe);
    263
    264	spin_unlock_irqrestore(&gpio_lock, flags);
    265
    266	return 0;
    267}
    268
    269static int
    270mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
    271{
    272	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
    273	struct mpc52xx_gpiochip *chip = gpiochip_get_data(gc);
    274	struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
    275	unsigned long flags;
    276
    277	spin_lock_irqsave(&gpio_lock, flags);
    278
    279	/* First set initial value */
    280	__mpc52xx_simple_gpio_set(gc, gpio, val);
    281
    282	/* Then set direction */
    283	chip->shadow_ddr |= 1 << (31 - gpio);
    284	out_be32(&regs->simple_ddr, chip->shadow_ddr);
    285
    286	/* Finally enable the pin */
    287	chip->shadow_gpioe |= 1 << (31 - gpio);
    288	out_be32(&regs->simple_gpioe, chip->shadow_gpioe);
    289
    290	spin_unlock_irqrestore(&gpio_lock, flags);
    291
    292	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
    293
    294	return 0;
    295}
    296
    297static int mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
    298{
    299	struct mpc52xx_gpiochip *chip;
    300	struct gpio_chip *gc;
    301	struct mpc52xx_gpio __iomem *regs;
    302	int ret;
    303
    304	chip = devm_kzalloc(&ofdev->dev, sizeof(*chip), GFP_KERNEL);
    305	if (!chip)
    306		return -ENOMEM;
    307
    308	platform_set_drvdata(ofdev, chip);
    309
    310	gc = &chip->mmchip.gc;
    311
    312	gc->ngpio            = 32;
    313	gc->direction_input  = mpc52xx_simple_gpio_dir_in;
    314	gc->direction_output = mpc52xx_simple_gpio_dir_out;
    315	gc->get              = mpc52xx_simple_gpio_get;
    316	gc->set              = mpc52xx_simple_gpio_set;
    317
    318	ret = of_mm_gpiochip_add_data(ofdev->dev.of_node, &chip->mmchip, chip);
    319	if (ret)
    320		return ret;
    321
    322	regs = chip->mmchip.regs;
    323	chip->shadow_gpioe = in_be32(&regs->simple_gpioe);
    324	chip->shadow_ddr = in_be32(&regs->simple_ddr);
    325	chip->shadow_dvo = in_be32(&regs->simple_dvo);
    326
    327	return 0;
    328}
    329
    330static const struct of_device_id mpc52xx_simple_gpiochip_match[] = {
    331	{ .compatible = "fsl,mpc5200-gpio", },
    332	{}
    333};
    334
    335static struct platform_driver mpc52xx_simple_gpiochip_driver = {
    336	.driver = {
    337		.name = "mpc5200-gpio",
    338		.of_match_table = mpc52xx_simple_gpiochip_match,
    339	},
    340	.probe = mpc52xx_simple_gpiochip_probe,
    341	.remove = mpc52xx_gpiochip_remove,
    342};
    343
    344static struct platform_driver * const drivers[] = {
    345	&mpc52xx_wkup_gpiochip_driver,
    346	&mpc52xx_simple_gpiochip_driver,
    347};
    348
    349static int __init mpc52xx_gpio_init(void)
    350{
    351	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
    352}
    353
    354/* Make sure we get initialised before anyone else tries to use us */
    355subsys_initcall(mpc52xx_gpio_init);
    356
    357static void __exit mpc52xx_gpio_exit(void)
    358{
    359	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
    360}
    361module_exit(mpc52xx_gpio_exit);
    362
    363MODULE_DESCRIPTION("Freescale MPC52xx gpio driver");
    364MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");
    365MODULE_LICENSE("GPL v2");
    366