Prev: [PATCH 1/1] mutex: prevent optimistic spinning from spinning longer than neccessary
Next: [PATCH RESEND] Calgary: increase max PHB number
From: Andrew Morton on 15 Jun 2010 16:10 On Fri, 11 Jun 2010 17:19:28 -0700 Gregory Bean <gbean(a)codeaurora.org> wrote: > Add support for uniprocessor MSM chips whose TLMM/GPIO design > is the same as the MSM7200A. > This includes, but is not necessarily limited to, the: > MSM7200A, MSM7x25, MSM7x27, MSM7x30, QSD8x50, QSD8x50A > > > ... > > +static inline unsigned bit(unsigned offset) > +{ > + BUG_ON(offset >= sizeof(unsigned) * 8); > + return 1U << offset; > +} Could use bitops.h's BIT(), but it hardly matters. > +/* > + * This function assumes that msm_gpio_dev::lock is held. > + */ > +static inline void set_gpio_bit(unsigned n, void __iomem *reg) > +{ > + writel(readl(reg) | bit(n), reg); > +} > + > +/* > + * This function assumes that msm_gpio_dev::lock is held. > + */ > +static inline void clr_gpio_bit(unsigned n, void __iomem *reg) > +{ > + writel(readl(reg) & ~bit(n), reg); > +} > + > +/* > + * This function assumes that msm_gpio_dev::lock is held. > + */ > +static inline void > +msm_gpio_write(struct msm_gpio_dev *dev, unsigned n, unsigned on) > +{ > + if (on) > + set_gpio_bit(n, dev->regs.out); > + else > + clr_gpio_bit(n, dev->regs.out); > +} Recent gcc's often uninline things whcih were marked inline. Doesn't matter much. > > ... > > +static int gpio_chip_get(struct gpio_chip *chip, unsigned offset) > +{ > + struct msm_gpio_dev *msm_gpio = TO_MSM_GPIO_DEV(chip); > + unsigned long irq_flags; > + int ret; > + > + spin_lock_irqsave(&msm_gpio->lock, irq_flags); > + ret = readl(msm_gpio->regs.in) & bit(offset) ? 1 : 0; > + spin_unlock_irqrestore(&msm_gpio->lock, irq_flags); > + > + return ret; > +} The locking here is actually unneeded, I expect. > +static void gpio_chip_set(struct gpio_chip *chip, unsigned offset, int value) > +{ > + struct msm_gpio_dev *msm_gpio = TO_MSM_GPIO_DEV(chip); > + unsigned long irq_flags; > + > + spin_lock_irqsave(&msm_gpio->lock, irq_flags); > + msm_gpio_write(msm_gpio, offset, value); > + spin_unlock_irqrestore(&msm_gpio->lock, irq_flags); > +} > + > +static int msm_gpio_probe(struct platform_device *dev) > +{ > + struct msm_gpio_dev *msm_gpio; > + struct msm7200a_gpio_platform_data *pdata = > + (struct msm7200a_gpio_platform_data *)dev->dev.platform_data; The the typecast of a void* is unneeded and undesirable because it defeats typechecking. > + int ret; > + > + if (!pdata) > + return -EINVAL; > + > + msm_gpio = kzalloc(sizeof(struct msm_gpio_dev), GFP_KERNEL); > + if (!msm_gpio) > + return -ENOMEM; > + > + spin_lock_init(&msm_gpio->lock); > + platform_set_drvdata(dev, msm_gpio); > + memcpy(&msm_gpio->regs, > + &pdata->regs, > + sizeof(struct msm7200a_gpio_regs)); > + > + msm_gpio->gpio_chip.label = dev->name; > + msm_gpio->gpio_chip.base = pdata->gpio_base; > + msm_gpio->gpio_chip.ngpio = pdata->ngpio; > + msm_gpio->gpio_chip.direction_input = gpio_chip_direction_input; > + msm_gpio->gpio_chip.direction_output = gpio_chip_direction_output; > + msm_gpio->gpio_chip.get = gpio_chip_get; > + msm_gpio->gpio_chip.set = gpio_chip_set; > + > + ret = gpiochip_add(&msm_gpio->gpio_chip); > + if (ret < 0) > + goto err_post_malloc; > + > + return ret; > +err_post_malloc: > + kfree(msm_gpio); Maybe undo platform_set_drvdata() here? > + return ret; > +} > + > > ... > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo(a)vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ |