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>
16 #include <dm/uclass-internal.h>
18 #define PCR_COMMON_IOSF_1_0 1
20 static void *_pcr_reg_address(struct udevice
*dev
, uint offset
)
22 struct p2sb_child_platdata
*pplat
= dev_get_parent_platdata(dev
);
23 struct udevice
*p2sb
= dev_get_parent(dev
);
24 struct p2sb_uc_priv
*upriv
= dev_get_uclass_priv(p2sb
);
27 /* Create an address based off of port id and offset */
28 reg_addr
= upriv
->mmio_base
;
29 reg_addr
+= pplat
->pid
<< PCR_PORTID_SHIFT
;
32 return map_sysmem(reg_addr
, 4);
36 * The mapping of addresses via the SBREG_BAR assumes the IOSF-SB
37 * agents are using 32-bit aligned accesses for their configuration
38 * registers. For IOSF versions greater than 1_0, IOSF-SB
39 * agents can use any access (8/16/32 bit aligned) for their
40 * configuration registers
42 static inline void check_pcr_offset_align(uint offset
, uint size
)
44 const size_t align
= PCR_COMMON_IOSF_1_0
? sizeof(uint32_t) : size
;
46 assert(IS_ALIGNED(offset
, align
));
49 uint
pcr_read32(struct udevice
*dev
, uint offset
)
54 /* Ensure the PCR offset is correctly aligned */
55 assert(IS_ALIGNED(offset
, sizeof(uint32_t)));
57 ptr
= _pcr_reg_address(dev
, offset
);
64 uint
pcr_read16(struct udevice
*dev
, uint offset
)
66 /* Ensure the PCR offset is correctly aligned */
67 check_pcr_offset_align(offset
, sizeof(uint16_t));
69 return readw(_pcr_reg_address(dev
, offset
));
72 uint
pcr_read8(struct udevice
*dev
, uint offset
)
74 /* Ensure the PCR offset is correctly aligned */
75 check_pcr_offset_align(offset
, sizeof(uint8_t));
77 return readb(_pcr_reg_address(dev
, offset
));
81 * After every write one needs to perform a read an innocuous register to
82 * ensure the writes are completed for certain ports. This is done for
83 * all ports so that the callers don't need the per-port knowledge for
86 static void write_completion(struct udevice
*dev
, uint offset
)
88 readl(_pcr_reg_address(dev
, ALIGN_DOWN(offset
, sizeof(uint32_t))));
91 void pcr_write32(struct udevice
*dev
, uint offset
, uint indata
)
93 /* Ensure the PCR offset is correctly aligned */
94 assert(IS_ALIGNED(offset
, sizeof(indata
)));
96 writel(indata
, _pcr_reg_address(dev
, offset
));
97 /* Ensure the writes complete */
98 write_completion(dev
, offset
);
101 void pcr_write16(struct udevice
*dev
, uint offset
, uint indata
)
103 /* Ensure the PCR offset is correctly aligned */
104 check_pcr_offset_align(offset
, sizeof(uint16_t));
106 writew(indata
, _pcr_reg_address(dev
, offset
));
107 /* Ensure the writes complete */
108 write_completion(dev
, offset
);
111 void pcr_write8(struct udevice
*dev
, uint offset
, uint indata
)
113 /* Ensure the PCR offset is correctly aligned */
114 check_pcr_offset_align(offset
, sizeof(uint8_t));
116 writeb(indata
, _pcr_reg_address(dev
, offset
));
117 /* Ensure the writes complete */
118 write_completion(dev
, offset
);
121 void pcr_clrsetbits32(struct udevice
*dev
, uint offset
, uint clr
, uint set
)
125 data32
= pcr_read32(dev
, offset
);
128 pcr_write32(dev
, offset
, data32
);
131 void pcr_clrsetbits16(struct udevice
*dev
, uint offset
, uint clr
, uint set
)
135 data16
= pcr_read16(dev
, offset
);
138 pcr_write16(dev
, offset
, data16
);
141 void pcr_clrsetbits8(struct udevice
*dev
, uint offset
, uint clr
, uint set
)
145 data8
= pcr_read8(dev
, offset
);
148 pcr_write8(dev
, offset
, data8
);
151 int p2sb_get_port_id(struct udevice
*dev
)
153 struct p2sb_child_platdata
*pplat
= dev_get_parent_platdata(dev
);
158 int p2sb_set_port_id(struct udevice
*dev
, int portid
)
160 struct udevice
*ps2b
;
161 struct p2sb_child_platdata
*pplat
;
163 if (!CONFIG_IS_ENABLED(OF_PLATDATA
))
166 uclass_find_first_device(UCLASS_P2SB
, &ps2b
);
172 * We must allocate this, since when the device was bound it did not
174 * TODO(sjg@chromium.org): Add a parent pointer to child devices in dtoc
176 dev
->parent_platdata
= malloc(sizeof(*pplat
));
177 if (!dev
->parent_platdata
)
179 pplat
= dev_get_parent_platdata(dev
);
185 static int p2sb_child_post_bind(struct udevice
*dev
)
187 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
188 struct p2sb_child_platdata
*pplat
= dev_get_parent_platdata(dev
);
192 ret
= dev_read_u32(dev
, "intel,p2sb-port-id", &pid
);
201 static int p2sb_post_bind(struct udevice
*dev
)
203 if (spl_phase() > PHASE_TPL
&& !CONFIG_IS_ENABLED(OF_PLATDATA
))
204 return dm_scan_fdt_dev(dev
);
209 UCLASS_DRIVER(p2sb
) = {
212 .per_device_auto_alloc_size
= sizeof(struct p2sb_uc_priv
),
213 .post_bind
= p2sb_post_bind
,
214 .child_post_bind
= p2sb_child_post_bind
,
215 .per_child_platdata_auto_alloc_size
=
216 sizeof(struct p2sb_child_platdata
),