xref: /aosp_15_r20/external/coreboot/src/soc/rockchip/rk3288/software_i2c.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/mmio.h>
4 #include <console/console.h>
5 #include <device/i2c_simple.h>
6 #include <gpio.h>
7 #include <soc/grf.h>
8 #include <soc/i2c.h>
9 #include <soc/pmu.h>
10 
11 static struct {
12 	gpio_t scl;
13 	gpio_t sda;
14 } pins[] = {
15 	[0]{.scl = GPIO(0, C, 0), .sda = GPIO(0, B, 7)},
16 	[1]{.scl = GPIO(8, A, 5), .sda = GPIO(8, A, 4)},
17 	[2]{.scl = GPIO(6, B, 2), .sda = GPIO(6, B, 1)},
18 	[3]{.scl = GPIO(2, C, 0), .sda = GPIO(2, C, 1)},
19 	[4]{.scl = GPIO(7, C, 2), .sda = GPIO(7, C, 1)},
20 	[5]{.scl = GPIO(7, C, 4), .sda = GPIO(7, C, 3)},
21 };
22 
get_scl(unsigned int bus)23 static int get_scl(unsigned int bus)
24 {
25 	return gpio_get(pins[bus].scl);
26 }
27 
get_sda(unsigned int bus)28 static int get_sda(unsigned int bus)
29 {
30 	return gpio_get(pins[bus].sda);
31 }
32 
set_scl(unsigned int bus,int high)33 static void set_scl(unsigned int bus, int high)
34 {
35 	if (high)
36 		gpio_input_pullup(pins[bus].scl);
37 	else
38 		gpio_output(pins[bus].scl, 0);
39 }
40 
set_sda(unsigned int bus,int high)41 static void set_sda(unsigned int bus, int high)
42 {
43 	if (high)
44 		gpio_input_pullup(pins[bus].sda);
45 	else
46 		gpio_output(pins[bus].sda, 0);
47 }
48 
49 static struct software_i2c_ops rk_ops = {
50 	.get_scl = get_scl,
51 	.get_sda = get_sda,
52 	.set_scl = set_scl,
53 	.set_sda = set_sda,
54 };
55 
software_i2c_attach(unsigned int bus)56 void software_i2c_attach(unsigned int bus)
57 {
58 	software_i2c[bus] = &rk_ops;
59 
60 	/* Mux pins to GPIO function for software I2C emulation. */
61 	switch (bus) {
62 	case 0:
63 		clrbits32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL);
64 		clrbits32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA);
65 		break;
66 	case 1:
67 		write32(&rk3288_grf->iomux_i2c1, IOMUX_GPIO(IOMUX_I2C1));
68 		break;
69 	case 2:
70 		write32(&rk3288_grf->iomux_i2c2, IOMUX_GPIO(IOMUX_I2C2));
71 		break;
72 	case 3:
73 		write32(&rk3288_grf->iomux_i2c3, IOMUX_GPIO(IOMUX_I2C3));
74 		break;
75 	case 4:
76 		write32(&rk3288_grf->iomux_i2c4, IOMUX_GPIO(IOMUX_I2C4));
77 		break;
78 	case 5:
79 		write32(&rk3288_grf->iomux_i2c5scl, IOMUX_GPIO(IOMUX_I2C5SCL));
80 		write32(&rk3288_grf->iomux_i2c5sda, IOMUX_GPIO(IOMUX_I2C5SDA));
81 		break;
82 	default:
83 		die("Unknown I2C bus number!");
84 	}
85 
86 	/* Initialize bus to idle state. */
87 	set_scl(bus, 1);
88 	set_sda(bus, 1);
89 }
90 
software_i2c_detach(unsigned int bus)91 void software_i2c_detach(unsigned int bus)
92 {
93 	software_i2c[bus] = NULL;
94 
95 	/* Mux pins back to hardware I2C controller. */
96 	switch (bus) {
97 	case 0:
98 		setbits32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL);
99 		setbits32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA);
100 		break;
101 	case 1:
102 		write32(&rk3288_grf->iomux_i2c1, IOMUX_I2C1);
103 		break;
104 	case 2:
105 		write32(&rk3288_grf->iomux_i2c2, IOMUX_I2C2);
106 		break;
107 	case 3:
108 		write32(&rk3288_grf->iomux_i2c3, IOMUX_I2C3);
109 		break;
110 	case 4:
111 		write32(&rk3288_grf->iomux_i2c4, IOMUX_I2C4);
112 		break;
113 	case 5:
114 		write32(&rk3288_grf->iomux_i2c5scl, IOMUX_I2C5SCL);
115 		write32(&rk3288_grf->iomux_i2c5sda, IOMUX_I2C5SDA);
116 		break;
117 	default:
118 		die("Unknown I2C bus number!");
119 	}
120 }
121