1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 *  Driver for the Conexant CX25821 PCIe bridge
4 *
5 *  Copyright (C) 2009 Conexant Systems Inc.
6 *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
7 */
8
9#include <linux/module.h>
10#include "cx25821.h"
11
12/********************* GPIO stuffs *********************/
13void cx25821_set_gpiopin_direction(struct cx25821_dev *dev,
14				   int pin_number, int pin_logic_value)
15{
16	int bit = pin_number;
17	u32 gpio_oe_reg = GPIO_LO_OE;
18	u32 gpio_register = 0;
19	u32 value = 0;
20
21	/* Check for valid pinNumber */
22	if (pin_number >= 47)
23		return;
24
25	if (pin_number > 31) {
26		bit = pin_number - 31;
27		gpio_oe_reg = GPIO_HI_OE;
28	}
29	/* Here we will make sure that the GPIOs 0 and 1 are output. keep the
30	 * rest as is */
31	gpio_register = cx_read(gpio_oe_reg);
32
33	if (pin_logic_value == 1)
34		value = gpio_register | Set_GPIO_Bit(bit);
35	else
36		value = gpio_register & Clear_GPIO_Bit(bit);
37
38	cx_write(gpio_oe_reg, value);
39}
40EXPORT_SYMBOL(cx25821_set_gpiopin_direction);
41
42static void cx25821_set_gpiopin_logicvalue(struct cx25821_dev *dev,
43					   int pin_number, int pin_logic_value)
44{
45	int bit = pin_number;
46	u32 gpio_reg = GPIO_LO;
47	u32 value = 0;
48
49	/* Check for valid pinNumber */
50	if (pin_number >= 47)
51		return;
52
53	/* change to output direction */
54	cx25821_set_gpiopin_direction(dev, pin_number, 0);
55
56	if (pin_number > 31) {
57		bit = pin_number - 31;
58		gpio_reg = GPIO_HI;
59	}
60
61	value = cx_read(gpio_reg);
62
63	if (pin_logic_value == 0)
64		value &= Clear_GPIO_Bit(bit);
65	else
66		value |= Set_GPIO_Bit(bit);
67
68	cx_write(gpio_reg, value);
69}
70
71void cx25821_gpio_init(struct cx25821_dev *dev)
72{
73	if (dev == NULL)
74		return;
75
76	switch (dev->board) {
77	case CX25821_BOARD_CONEXANT_ATHENA10:
78	default:
79		/* set GPIO 5 to select the path for Medusa/Athena */
80		cx25821_set_gpiopin_logicvalue(dev, 5, 1);
81		msleep(20);
82		break;
83	}
84
85}
86