1 // SPDX-License-Identifier: GPL-2.0+
3 * Uclass for Primary-to-sideband bus, used to access various peripherals
5 * Copyright 2019 Google LLC
6 * Written by Simon Glass <sjg@chromium.org>
17 #include <dm/uclass-internal.h>
19 #define PCR_COMMON_IOSF_1_0 1
21 int p2sb_set_hide(struct udevice *dev, bool hide)
23 struct p2sb_ops *ops = p2sb_get_ops(dev);
28 return ops->set_hide(dev, hide);
31 void *pcr_reg_address(struct udevice *dev, uint offset)
33 struct p2sb_child_platdata *pplat = dev_get_parent_plat(dev);
34 struct udevice *p2sb = dev_get_parent(dev);
35 struct p2sb_uc_priv *upriv = dev_get_uclass_priv(p2sb);
38 /* Create an address based off of port id and offset */
39 reg_addr = upriv->mmio_base;
40 reg_addr += pplat->pid << PCR_PORTID_SHIFT;
43 return map_sysmem(reg_addr, 4);
47 * The mapping of addresses via the SBREG_BAR assumes the IOSF-SB
48 * agents are using 32-bit aligned accesses for their configuration
49 * registers. For IOSF versions greater than 1_0, IOSF-SB
50 * agents can use any access (8/16/32 bit aligned) for their
51 * configuration registers
53 static inline void check_pcr_offset_align(uint offset, uint size)
55 const size_t align = PCR_COMMON_IOSF_1_0 ? sizeof(uint32_t) : size;
57 assert(IS_ALIGNED(offset, align));
60 uint pcr_read32(struct udevice *dev, uint offset)
65 /* Ensure the PCR offset is correctly aligned */
66 assert(IS_ALIGNED(offset, sizeof(uint32_t)));
68 ptr = pcr_reg_address(dev, offset);
75 uint pcr_read16(struct udevice *dev, uint offset)
77 /* Ensure the PCR offset is correctly aligned */
78 check_pcr_offset_align(offset, sizeof(uint16_t));
80 return readw(pcr_reg_address(dev, offset));
83 uint pcr_read8(struct udevice *dev, uint offset)
85 /* Ensure the PCR offset is correctly aligned */
86 check_pcr_offset_align(offset, sizeof(uint8_t));
88 return readb(pcr_reg_address(dev, offset));
92 * After every write one needs to perform a read an innocuous register to
93 * ensure the writes are completed for certain ports. This is done for
94 * all ports so that the callers don't need the per-port knowledge for
97 static void write_completion(struct udevice *dev, uint offset)
99 readl(pcr_reg_address(dev, ALIGN_DOWN(offset, sizeof(uint32_t))));
102 void pcr_write32(struct udevice *dev, uint offset, uint indata)
104 /* Ensure the PCR offset is correctly aligned */
105 assert(IS_ALIGNED(offset, sizeof(indata)));
107 writel(indata, pcr_reg_address(dev, offset));
108 /* Ensure the writes complete */
109 write_completion(dev, offset);
112 void pcr_write16(struct udevice *dev, uint offset, uint indata)
114 /* Ensure the PCR offset is correctly aligned */
115 check_pcr_offset_align(offset, sizeof(uint16_t));
117 writew(indata, pcr_reg_address(dev, offset));
118 /* Ensure the writes complete */
119 write_completion(dev, offset);
122 void pcr_write8(struct udevice *dev, uint offset, uint indata)
124 /* Ensure the PCR offset is correctly aligned */
125 check_pcr_offset_align(offset, sizeof(uint8_t));
127 writeb(indata, pcr_reg_address(dev, offset));
128 /* Ensure the writes complete */
129 write_completion(dev, offset);
132 void pcr_clrsetbits32(struct udevice *dev, uint offset, uint clr, uint set)
136 data32 = pcr_read32(dev, offset);
139 pcr_write32(dev, offset, data32);
142 void pcr_clrsetbits16(struct udevice *dev, uint offset, uint clr, uint set)
146 data16 = pcr_read16(dev, offset);
149 pcr_write16(dev, offset, data16);
152 void pcr_clrsetbits8(struct udevice *dev, uint offset, uint clr, uint set)
156 data8 = pcr_read8(dev, offset);
159 pcr_write8(dev, offset, data8);
162 int p2sb_get_port_id(struct udevice *dev)
164 struct p2sb_child_platdata *pplat = dev_get_parent_plat(dev);
169 int p2sb_set_port_id(struct udevice *dev, int portid)
171 struct udevice *ps2b;
172 struct p2sb_child_platdata *pplat;
174 if (!CONFIG_IS_ENABLED(OF_PLATDATA))
177 if (!CONFIG_IS_ENABLED(OF_PLATDATA_PARENT)) {
178 uclass_find_first_device(UCLASS_P2SB, &ps2b);
184 * We must allocate this, since when the device was bound it did
187 dev->parent_plat = malloc(sizeof(*pplat));
188 if (!dev->parent_plat)
191 pplat = dev_get_parent_plat(dev);
197 static int p2sb_child_post_bind(struct udevice *dev)
199 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
200 struct p2sb_child_platdata *pplat = dev_get_parent_plat(dev);
204 ret = dev_read_u32(dev, "intel,p2sb-port-id", &pid);
213 static int p2sb_post_bind(struct udevice *dev)
215 if (spl_phase() > PHASE_TPL && !CONFIG_IS_ENABLED(OF_PLATDATA))
216 return dm_scan_fdt_dev(dev);
221 UCLASS_DRIVER(p2sb) = {
224 .per_device_auto = sizeof(struct p2sb_uc_priv),
225 .post_bind = p2sb_post_bind,
226 .child_post_bind = p2sb_child_post_bind,
227 .per_child_plat_auto =
228 sizeof(struct p2sb_child_platdata),