brintos

brintos / linux-shallow public Read only

0
0
Text · 13.0 KiB · d6418f8 Raw
460 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2 3#include <linux/gpio/driver.h>4#include <linux/cpumask.h>5#include <linux/irq.h>6#include <linux/minmax.h>7#include <linux/mod_devicetable.h>8#include <linux/module.h>9#include <linux/platform_device.h>10#include <linux/property.h>11 12/*13 * Total register block size is 0x1C for one bank of four ports (A, B, C, D).14 * An optional second bank, with ports E, F, G, and H, may be present, starting15 * at register offset 0x1C.16 */17 18/*19 * Pin select: (0) "normal", (1) "dedicate peripheral"20 * Not used on RTL8380/RTL8390, peripheral selection is managed by control bits21 * in the peripheral registers.22 */23#define REALTEK_GPIO_REG_CNR		0x0024/* Clear bit (0) for input, set bit (1) for output */25#define REALTEK_GPIO_REG_DIR		0x0826#define REALTEK_GPIO_REG_DATA		0x0C27/* Read bit for IRQ status, write 1 to clear IRQ */28#define REALTEK_GPIO_REG_ISR		0x1029/* Two bits per GPIO in IMR registers */30#define REALTEK_GPIO_REG_IMR		0x1431#define REALTEK_GPIO_REG_IMR_AB		0x1432#define REALTEK_GPIO_REG_IMR_CD		0x1833#define REALTEK_GPIO_IMR_LINE_MASK	GENMASK(1, 0)34#define REALTEK_GPIO_IRQ_EDGE_FALLING	135#define REALTEK_GPIO_IRQ_EDGE_RISING	236#define REALTEK_GPIO_IRQ_EDGE_BOTH	337 38#define REALTEK_GPIO_MAX		3239#define REALTEK_GPIO_PORTS_PER_BANK	440 41/**42 * realtek_gpio_ctrl - Realtek Otto GPIO driver data43 *44 * @gc: Associated gpio_chip instance45 * @base: Base address of the register block for a GPIO bank46 * @lock: Lock for accessing the IRQ registers and values47 * @intr_mask: Mask for interrupts lines48 * @intr_type: Interrupt type selection49 * @bank_read: Read a bank setting as a single 32-bit value50 * @bank_write: Write a bank setting as a single 32-bit value51 * @imr_line_pos: Bit shift of an IRQ line's IMR value.52 *53 * The DIR, DATA, and ISR registers consist of four 8-bit port values, packed54 * into a single 32-bit register. Use @bank_read (@bank_write) to get (assign)55 * a value from (to) these registers. The IMR register consists of four 16-bit56 * port values, packed into two 32-bit registers. Use @imr_line_pos to get the57 * bit shift of the 2-bit field for a line's IMR settings. Shifts larger than58 * 32 overflow into the second register.59 *60 * Because the interrupt mask register (IMR) combines the function of IRQ type61 * selection and masking, two extra values are stored. @intr_mask is used to62 * mask/unmask the interrupts for a GPIO line, and @intr_type is used to store63 * the selected interrupt types. The logical AND of these values is written to64 * IMR on changes.65 */66struct realtek_gpio_ctrl {67	struct gpio_chip gc;68	void __iomem *base;69	void __iomem *cpumask_base;70	struct cpumask cpu_irq_maskable;71	raw_spinlock_t lock;72	u8 intr_mask[REALTEK_GPIO_MAX];73	u8 intr_type[REALTEK_GPIO_MAX];74	u32 (*bank_read)(void __iomem *reg);75	void (*bank_write)(void __iomem *reg, u32 value);76	unsigned int (*line_imr_pos)(unsigned int line);77};78 79/* Expand with more flags as devices with other quirks are added */80enum realtek_gpio_flags {81	/*82	 * Allow disabling interrupts, for cases where the port order is83	 * unknown. This may result in a port mismatch between ISR and IMR.84	 * An interrupt would appear to come from a different line than the85	 * line the IRQ handler was assigned to, causing uncaught interrupts.86	 */87	GPIO_INTERRUPTS_DISABLED = BIT(0),88	/*89	 * Port order is reversed, meaning DCBA register layout for 1-bit90	 * fields, and [BA, DC] for 2-bit fields.91	 */92	GPIO_PORTS_REVERSED = BIT(1),93	/*94	 * Interrupts can be enabled per cpu. This requires a secondary IO95	 * range, where the per-cpu enable masks are located.96	 */97	GPIO_INTERRUPTS_PER_CPU = BIT(2),98};99 100static struct realtek_gpio_ctrl *irq_data_to_ctrl(struct irq_data *data)101{102	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);103 104	return container_of(gc, struct realtek_gpio_ctrl, gc);105}106 107/*108 * Normal port order register access109 *110 * Port information is stored with the first port at offset 0, followed by the111 * second, etc. Most registers store one bit per GPIO and use a u8 value per112 * port. The two interrupt mask registers store two bits per GPIO, so use u16113 * values.114 */115static u32 realtek_gpio_bank_read_swapped(void __iomem *reg)116{117	return ioread32be(reg);118}119 120static void realtek_gpio_bank_write_swapped(void __iomem *reg, u32 value)121{122	iowrite32be(value, reg);123}124 125static unsigned int realtek_gpio_line_imr_pos_swapped(unsigned int line)126{127	unsigned int port_pin = line % 8;128	unsigned int port = line / 8;129 130	return 2 * (8 * (port ^ 1) + port_pin);131}132 133/*134 * Reversed port order register access135 *136 * For registers with one bit per GPIO, all ports are stored as u8-s in one137 * register in reversed order. The two interrupt mask registers store two bits138 * per GPIO, so use u16 values. The first register contains ports 1 and 0, the139 * second ports 3 and 2.140 */141static u32 realtek_gpio_bank_read(void __iomem *reg)142{143	return ioread32(reg);144}145 146static void realtek_gpio_bank_write(void __iomem *reg, u32 value)147{148	iowrite32(value, reg);149}150 151static unsigned int realtek_gpio_line_imr_pos(unsigned int line)152{153	return 2 * line;154}155 156static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl, u32 mask)157{158	ctrl->bank_write(ctrl->base + REALTEK_GPIO_REG_ISR, mask);159}160 161static u32 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl)162{163	return ctrl->bank_read(ctrl->base + REALTEK_GPIO_REG_ISR);164}165 166/* Set the rising and falling edge mask bits for a GPIO pin */167static void realtek_gpio_update_line_imr(struct realtek_gpio_ctrl *ctrl, unsigned int line)168{169	void __iomem *reg = ctrl->base + REALTEK_GPIO_REG_IMR;170	unsigned int line_shift = ctrl->line_imr_pos(line);171	unsigned int shift = line_shift % 32;172	u32 irq_type = ctrl->intr_type[line];173	u32 irq_mask = ctrl->intr_mask[line];174	u32 reg_val;175 176	reg += 4 * (line_shift / 32);177	reg_val = ioread32(reg);178	reg_val &= ~(REALTEK_GPIO_IMR_LINE_MASK << shift);179	reg_val |= (irq_type & irq_mask & REALTEK_GPIO_IMR_LINE_MASK) << shift;180	iowrite32(reg_val, reg);181}182 183static void realtek_gpio_irq_ack(struct irq_data *data)184{185	struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);186	irq_hw_number_t line = irqd_to_hwirq(data);187 188	realtek_gpio_clear_isr(ctrl, BIT(line));189}190 191static void realtek_gpio_irq_unmask(struct irq_data *data)192{193	struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);194	unsigned int line = irqd_to_hwirq(data);195	unsigned long flags;196 197	gpiochip_enable_irq(&ctrl->gc, line);198 199	raw_spin_lock_irqsave(&ctrl->lock, flags);200	ctrl->intr_mask[line] = REALTEK_GPIO_IMR_LINE_MASK;201	realtek_gpio_update_line_imr(ctrl, line);202	raw_spin_unlock_irqrestore(&ctrl->lock, flags);203}204 205static void realtek_gpio_irq_mask(struct irq_data *data)206{207	struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);208	unsigned int line = irqd_to_hwirq(data);209	unsigned long flags;210 211	raw_spin_lock_irqsave(&ctrl->lock, flags);212	ctrl->intr_mask[line] = 0;213	realtek_gpio_update_line_imr(ctrl, line);214	raw_spin_unlock_irqrestore(&ctrl->lock, flags);215 216	gpiochip_disable_irq(&ctrl->gc, line);217}218 219static int realtek_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)220{221	struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);222	unsigned int line = irqd_to_hwirq(data);223	unsigned long flags;224	u8 type;225 226	switch (flow_type & IRQ_TYPE_SENSE_MASK) {227	case IRQ_TYPE_EDGE_FALLING:228		type = REALTEK_GPIO_IRQ_EDGE_FALLING;229		break;230	case IRQ_TYPE_EDGE_RISING:231		type = REALTEK_GPIO_IRQ_EDGE_RISING;232		break;233	case IRQ_TYPE_EDGE_BOTH:234		type = REALTEK_GPIO_IRQ_EDGE_BOTH;235		break;236	default:237		return -EINVAL;238	}239 240	irq_set_handler_locked(data, handle_edge_irq);241 242	raw_spin_lock_irqsave(&ctrl->lock, flags);243	ctrl->intr_type[line] = type;244	realtek_gpio_update_line_imr(ctrl, line);245	raw_spin_unlock_irqrestore(&ctrl->lock, flags);246 247	return 0;248}249 250static void realtek_gpio_irq_handler(struct irq_desc *desc)251{252	struct gpio_chip *gc = irq_desc_get_handler_data(desc);253	struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);254	struct irq_chip *irq_chip = irq_desc_get_chip(desc);255	unsigned long status;256	int offset;257 258	chained_irq_enter(irq_chip, desc);259 260	status = realtek_gpio_read_isr(ctrl);261	for_each_set_bit(offset, &status, gc->ngpio)262		generic_handle_domain_irq(gc->irq.domain, offset);263 264	chained_irq_exit(irq_chip, desc);265}266 267static inline void __iomem *realtek_gpio_irq_cpu_mask(struct realtek_gpio_ctrl *ctrl, int cpu)268{269	return ctrl->cpumask_base + REALTEK_GPIO_PORTS_PER_BANK * cpu;270}271 272static int realtek_gpio_irq_set_affinity(struct irq_data *data,273	const struct cpumask *dest, bool force)274{275	struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);276	unsigned int line = irqd_to_hwirq(data);277	void __iomem *irq_cpu_mask;278	unsigned long flags;279	int cpu;280	u32 v;281 282	if (!ctrl->cpumask_base)283		return -ENXIO;284 285	raw_spin_lock_irqsave(&ctrl->lock, flags);286 287	for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {288		irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, cpu);289		v = ctrl->bank_read(irq_cpu_mask);290 291		if (cpumask_test_cpu(cpu, dest))292			v |= BIT(line);293		else294			v &= ~BIT(line);295 296		ctrl->bank_write(irq_cpu_mask, v);297	}298 299	raw_spin_unlock_irqrestore(&ctrl->lock, flags);300 301	irq_data_update_effective_affinity(data, dest);302 303	return 0;304}305 306static int realtek_gpio_irq_init(struct gpio_chip *gc)307{308	struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);309	u32 mask_all = GENMASK(gc->ngpio - 1, 0);310	unsigned int line;311	int cpu;312 313	for (line = 0; line < gc->ngpio; line++)314		realtek_gpio_update_line_imr(ctrl, line);315 316	realtek_gpio_clear_isr(ctrl, mask_all);317 318	for_each_cpu(cpu, &ctrl->cpu_irq_maskable)319		ctrl->bank_write(realtek_gpio_irq_cpu_mask(ctrl, cpu), mask_all);320 321	return 0;322}323 324static const struct irq_chip realtek_gpio_irq_chip = {325	.name = "realtek-otto-gpio",326	.irq_ack = realtek_gpio_irq_ack,327	.irq_mask = realtek_gpio_irq_mask,328	.irq_unmask = realtek_gpio_irq_unmask,329	.irq_set_type = realtek_gpio_irq_set_type,330	.irq_set_affinity = realtek_gpio_irq_set_affinity,331	.flags = IRQCHIP_IMMUTABLE,332	GPIOCHIP_IRQ_RESOURCE_HELPERS,333};334 335static const struct of_device_id realtek_gpio_of_match[] = {336	{337		.compatible = "realtek,otto-gpio",338		.data = (void *)GPIO_INTERRUPTS_DISABLED,339	},340	{341		.compatible = "realtek,rtl8380-gpio",342	},343	{344		.compatible = "realtek,rtl8390-gpio",345	},346	{347		.compatible = "realtek,rtl9300-gpio",348		.data = (void *)(GPIO_PORTS_REVERSED | GPIO_INTERRUPTS_PER_CPU)349	},350	{351		.compatible = "realtek,rtl9310-gpio",352	},353	{}354};355MODULE_DEVICE_TABLE(of, realtek_gpio_of_match);356 357static int realtek_gpio_probe(struct platform_device *pdev)358{359	struct device *dev = &pdev->dev;360	unsigned long bgpio_flags;361	unsigned int dev_flags;362	struct gpio_irq_chip *girq;363	struct realtek_gpio_ctrl *ctrl;364	struct resource *res;365	u32 ngpios;366	unsigned int nr_cpus;367	int cpu, err, irq;368 369	ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);370	if (!ctrl)371		return -ENOMEM;372 373	dev_flags = (unsigned int) device_get_match_data(dev);374 375	ngpios = REALTEK_GPIO_MAX;376	device_property_read_u32(dev, "ngpios", &ngpios);377 378	if (ngpios > REALTEK_GPIO_MAX) {379		dev_err(&pdev->dev, "invalid ngpios (max. %d)\n",380			REALTEK_GPIO_MAX);381		return -EINVAL;382	}383 384	ctrl->base = devm_platform_ioremap_resource(pdev, 0);385	if (IS_ERR(ctrl->base))386		return PTR_ERR(ctrl->base);387 388	raw_spin_lock_init(&ctrl->lock);389 390	if (dev_flags & GPIO_PORTS_REVERSED) {391		bgpio_flags = 0;392		ctrl->bank_read = realtek_gpio_bank_read;393		ctrl->bank_write = realtek_gpio_bank_write;394		ctrl->line_imr_pos = realtek_gpio_line_imr_pos;395	} else {396		bgpio_flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;397		ctrl->bank_read = realtek_gpio_bank_read_swapped;398		ctrl->bank_write = realtek_gpio_bank_write_swapped;399		ctrl->line_imr_pos = realtek_gpio_line_imr_pos_swapped;400	}401 402	err = bgpio_init(&ctrl->gc, dev, 4,403		ctrl->base + REALTEK_GPIO_REG_DATA, NULL, NULL,404		ctrl->base + REALTEK_GPIO_REG_DIR, NULL,405		bgpio_flags);406	if (err) {407		dev_err(dev, "unable to init generic GPIO");408		return err;409	}410 411	ctrl->gc.ngpio = ngpios;412	ctrl->gc.owner = THIS_MODULE;413 414	irq = platform_get_irq_optional(pdev, 0);415	if (!(dev_flags & GPIO_INTERRUPTS_DISABLED) && irq > 0) {416		girq = &ctrl->gc.irq;417		gpio_irq_chip_set_chip(girq, &realtek_gpio_irq_chip);418		girq->default_type = IRQ_TYPE_NONE;419		girq->handler = handle_bad_irq;420		girq->parent_handler = realtek_gpio_irq_handler;421		girq->num_parents = 1;422		girq->parents = devm_kcalloc(dev, girq->num_parents,423					sizeof(*girq->parents),	GFP_KERNEL);424		if (!girq->parents)425			return -ENOMEM;426		girq->parents[0] = irq;427		girq->init_hw = realtek_gpio_irq_init;428	}429 430	cpumask_clear(&ctrl->cpu_irq_maskable);431 432	if ((dev_flags & GPIO_INTERRUPTS_PER_CPU) && irq > 0) {433		ctrl->cpumask_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res);434		if (IS_ERR(ctrl->cpumask_base))435			return dev_err_probe(dev, PTR_ERR(ctrl->cpumask_base),436				"missing CPU IRQ mask registers");437 438		nr_cpus = resource_size(res) / REALTEK_GPIO_PORTS_PER_BANK;439		nr_cpus = min(nr_cpus, num_present_cpus());440 441		for (cpu = 0; cpu < nr_cpus; cpu++)442			cpumask_set_cpu(cpu, &ctrl->cpu_irq_maskable);443	}444 445	return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl);446}447 448static struct platform_driver realtek_gpio_driver = {449	.driver = {450		.name = "realtek-otto-gpio",451		.of_match_table	= realtek_gpio_of_match,452	},453	.probe = realtek_gpio_probe,454};455module_platform_driver(realtek_gpio_driver);456 457MODULE_DESCRIPTION("Realtek Otto GPIO support");458MODULE_AUTHOR("Sander Vanheule <sander@svanheule.net>");459MODULE_LICENSE("GPL v2");460