Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'bitmap-for-6.18' of https://github.com/norov/linux

Pull bitmap updates from Yury Norov:

- FIELD_PREP_WM16() consolidation (Nicolas)

- bitmaps for Rust (Burak)

- __fls() fix for arc (Kees)

* tag 'bitmap-for-6.18' of https://github.com/norov/linux: (25 commits)
rust: add dynamic ID pool abstraction for bitmap
rust: add find_bit_benchmark_rust module.
rust: add bitmap API.
rust: add bindings for bitops.h
rust: add bindings for bitmap.h
phy: rockchip-pcie: switch to FIELD_PREP_WM16 macro
clk: sp7021: switch to FIELD_PREP_WM16 macro
PCI: dw-rockchip: Switch to FIELD_PREP_WM16 macro
PCI: rockchip: Switch to FIELD_PREP_WM16* macros
net: stmmac: dwmac-rk: switch to FIELD_PREP_WM16 macro
ASoC: rockchip: i2s-tdm: switch to FIELD_PREP_WM16_CONST macro
drm/rockchip: dw_hdmi: switch to FIELD_PREP_WM16* macros
phy: rockchip-usb: switch to FIELD_PREP_WM16 macro
drm/rockchip: inno-hdmi: switch to FIELD_PREP_WM16 macro
drm/rockchip: dw_hdmi_qp: switch to FIELD_PREP_WM16 macro
phy: rockchip-samsung-dcphy: switch to FIELD_PREP_WM16 macro
drm/rockchip: vop2: switch to FIELD_PREP_WM16 macro
drm/rockchip: dsi: switch to FIELD_PREP_WM16* macros
phy: rockchip-emmc: switch to FIELD_PREP_WM16 macro
drm/rockchip: lvds: switch to FIELD_PREP_WM16 macro
...

+1361 -338
+16
MAINTAINERS
··· 4298 4298 F: include/linux/cpumask.h 4299 4299 F: include/linux/cpumask_types.h 4300 4300 F: include/linux/find.h 4301 + F: include/linux/hw_bitfield.h 4301 4302 F: include/linux/nodemask.h 4302 4303 F: include/linux/nodemask_types.h 4303 4304 F: include/uapi/linux/bits.h ··· 4322 4321 BITMAP API BINDINGS [RUST] 4323 4322 M: Yury Norov <yury.norov@gmail.com> 4324 4323 S: Maintained 4324 + F: rust/helpers/bitmap.c 4325 4325 F: rust/helpers/cpumask.c 4326 + 4327 + BITMAP API [RUST] 4328 + M: Alice Ryhl <aliceryhl@google.com> 4329 + M: Burak Emir <bqe@google.com> 4330 + R: Yury Norov <yury.norov@gmail.com> 4331 + S: Maintained 4332 + F: lib/find_bit_benchmark_rust.rs 4333 + F: rust/kernel/bitmap.rs 4334 + F: rust/kernel/id_pool.rs 4326 4335 4327 4336 BITOPS API 4328 4337 M: Yury Norov <yury.norov@gmail.com> ··· 4347 4336 F: include/linux/bitops.h 4348 4337 F: lib/test_bitops.c 4349 4338 F: tools/*/bitops* 4339 + 4340 + BITOPS API BINDINGS [RUST] 4341 + M: Yury Norov <yury.norov@gmail.com> 4342 + S: Maintained 4343 + F: rust/helpers/bitops.c 4350 4344 4351 4345 BLINKM RGB LED DRIVER 4352 4346 M: Jan-Simon Moeller <jansimon.moeller@gmx.de>
+2
arch/arc/include/asm/bitops.h
··· 133 133 */ 134 134 static inline __attribute__ ((const)) unsigned long __fls(unsigned long x) 135 135 { 136 + if (__builtin_constant_p(x)) 137 + return x ? BITS_PER_LONG - 1 - __builtin_clzl(x) : 0; 136 138 /* FLS insn has exactly same semantics as the API */ 137 139 return __builtin_arc_fls(x); 138 140 }
+8 -14
drivers/clk/clk-sp7021.c
··· 7 7 #include <linux/clk-provider.h> 8 8 #include <linux/of.h> 9 9 #include <linux/bitfield.h> 10 + #include <linux/hw_bitfield.h> 10 11 #include <linux/slab.h> 11 12 #include <linux/io.h> 12 13 #include <linux/err.h> ··· 38 37 #define MASK_DIVR GENMASK(8, 7) 39 38 #define MASK_DIVN GENMASK(7, 0) 40 39 #define MASK_DIVM GENMASK(14, 8) 41 - 42 - /* HIWORD_MASK FIELD_PREP */ 43 - #define HWM_FIELD_PREP(mask, value) \ 44 - ({ \ 45 - u64 _m = mask; \ 46 - (_m << 16) | FIELD_PREP(_m, value); \ 47 - }) 48 40 49 41 struct sp_pll { 50 42 struct clk_hw hw; ··· 307 313 u32 r0, r1, r2; 308 314 309 315 r0 = BIT(clk->bp_bit + 16); 310 - r0 |= HWM_FIELD_PREP(MASK_SEL_FRA, clk->p[SEL_FRA]); 311 - r0 |= HWM_FIELD_PREP(MASK_SDM_MOD, clk->p[SDM_MOD]); 312 - r0 |= HWM_FIELD_PREP(MASK_PH_SEL, clk->p[PH_SEL]); 313 - r0 |= HWM_FIELD_PREP(MASK_NFRA, clk->p[NFRA]); 316 + r0 |= FIELD_PREP_WM16(MASK_SEL_FRA, clk->p[SEL_FRA]); 317 + r0 |= FIELD_PREP_WM16(MASK_SDM_MOD, clk->p[SDM_MOD]); 318 + r0 |= FIELD_PREP_WM16(MASK_PH_SEL, clk->p[PH_SEL]); 319 + r0 |= FIELD_PREP_WM16(MASK_NFRA, clk->p[NFRA]); 314 320 315 - r1 = HWM_FIELD_PREP(MASK_DIVR, clk->p[DIVR]); 321 + r1 = FIELD_PREP_WM16(MASK_DIVR, clk->p[DIVR]); 316 322 317 - r2 = HWM_FIELD_PREP(MASK_DIVN, clk->p[DIVN] - 1); 318 - r2 |= HWM_FIELD_PREP(MASK_DIVM, clk->p[DIVM] - 1); 323 + r2 = FIELD_PREP_WM16(MASK_DIVN, clk->p[DIVN] - 1); 324 + r2 |= FIELD_PREP_WM16(MASK_DIVM, clk->p[DIVM] - 1); 319 325 320 326 spin_lock_irqsave(&clk->lock, flags); 321 327 writel(r0, clk->reg);
+68 -74
drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
··· 7 7 */ 8 8 9 9 #include <linux/clk.h> 10 + #include <linux/hw_bitfield.h> 10 11 #include <linux/iopoll.h> 11 12 #include <linux/math64.h> 12 13 #include <linux/mfd/syscon.h> ··· 149 148 #define DW_MIPI_NEEDS_GRF_CLK BIT(1) 150 149 151 150 #define PX30_GRF_PD_VO_CON1 0x0438 152 - #define PX30_DSI_FORCETXSTOPMODE (0xf << 7) 151 + #define PX30_DSI_FORCETXSTOPMODE (0xfUL << 7) 153 152 #define PX30_DSI_FORCERXMODE BIT(6) 154 153 #define PX30_DSI_TURNDISABLE BIT(5) 155 154 #define PX30_DSI_LCDC_SEL BIT(0) ··· 168 167 #define RK3399_DSI1_LCDC_SEL BIT(4) 169 168 170 169 #define RK3399_GRF_SOC_CON22 0x6258 171 - #define RK3399_DSI0_TURNREQUEST (0xf << 12) 172 - #define RK3399_DSI0_TURNDISABLE (0xf << 8) 173 - #define RK3399_DSI0_FORCETXSTOPMODE (0xf << 4) 174 - #define RK3399_DSI0_FORCERXMODE (0xf << 0) 170 + #define RK3399_DSI0_TURNREQUEST (0xfUL << 12) 171 + #define RK3399_DSI0_TURNDISABLE (0xfUL << 8) 172 + #define RK3399_DSI0_FORCETXSTOPMODE (0xfUL << 4) 173 + #define RK3399_DSI0_FORCERXMODE (0xfUL << 0) 175 174 176 175 #define RK3399_GRF_SOC_CON23 0x625c 177 - #define RK3399_DSI1_TURNDISABLE (0xf << 12) 178 - #define RK3399_DSI1_FORCETXSTOPMODE (0xf << 8) 179 - #define RK3399_DSI1_FORCERXMODE (0xf << 4) 180 - #define RK3399_DSI1_ENABLE (0xf << 0) 176 + #define RK3399_DSI1_TURNDISABLE (0xfUL << 12) 177 + #define RK3399_DSI1_FORCETXSTOPMODE (0xfUL << 8) 178 + #define RK3399_DSI1_FORCERXMODE (0xfUL << 4) 179 + #define RK3399_DSI1_ENABLE (0xfUL << 0) 181 180 182 181 #define RK3399_GRF_SOC_CON24 0x6260 183 182 #define RK3399_TXRX_MASTERSLAVEZ BIT(7) ··· 187 186 #define RK3399_TXRX_TURNREQUEST GENMASK(3, 0) 188 187 189 188 #define RK3568_GRF_VO_CON2 0x0368 190 - #define RK3568_DSI0_SKEWCALHS (0x1f << 11) 191 - #define RK3568_DSI0_FORCETXSTOPMODE (0xf << 4) 189 + #define RK3568_DSI0_SKEWCALHS (0x1fUL << 11) 190 + #define RK3568_DSI0_FORCETXSTOPMODE (0xfUL << 4) 192 191 #define RK3568_DSI0_TURNDISABLE BIT(2) 193 192 #define RK3568_DSI0_FORCERXMODE BIT(0) 194 193 ··· 198 197 * come from. Name GRF_VO_CON3 is assumed. 199 198 */ 200 199 #define RK3568_GRF_VO_CON3 0x36c 201 - #define RK3568_DSI1_SKEWCALHS (0x1f << 11) 202 - #define RK3568_DSI1_FORCETXSTOPMODE (0xf << 4) 200 + #define RK3568_DSI1_SKEWCALHS (0x1fUL << 11) 201 + #define RK3568_DSI1_FORCETXSTOPMODE (0xfUL << 4) 203 202 #define RK3568_DSI1_TURNDISABLE BIT(2) 204 203 #define RK3568_DSI1_FORCERXMODE BIT(0) 205 204 206 205 #define RV1126_GRF_DSIPHY_CON 0x10220 207 - #define RV1126_DSI_FORCETXSTOPMODE (0xf << 4) 206 + #define RV1126_DSI_FORCETXSTOPMODE (0xfUL << 4) 208 207 #define RV1126_DSI_TURNDISABLE BIT(2) 209 208 #define RV1126_DSI_FORCERXMODE BIT(0) 210 - 211 - #define HIWORD_UPDATE(val, mask) (val | (mask) << 16) 212 209 213 210 enum { 214 211 DW_DSI_USAGE_IDLE, ··· 1483 1484 { 1484 1485 .reg = 0xff450000, 1485 1486 .lcdsel_grf_reg = PX30_GRF_PD_VO_CON1, 1486 - .lcdsel_big = HIWORD_UPDATE(0, PX30_DSI_LCDC_SEL), 1487 - .lcdsel_lit = HIWORD_UPDATE(PX30_DSI_LCDC_SEL, 1488 - PX30_DSI_LCDC_SEL), 1487 + .lcdsel_big = FIELD_PREP_WM16_CONST(PX30_DSI_LCDC_SEL, 0), 1488 + .lcdsel_lit = FIELD_PREP_WM16_CONST(PX30_DSI_LCDC_SEL, 1), 1489 1489 1490 1490 .lanecfg1_grf_reg = PX30_GRF_PD_VO_CON1, 1491 - .lanecfg1 = HIWORD_UPDATE(0, PX30_DSI_TURNDISABLE | 1492 - PX30_DSI_FORCERXMODE | 1493 - PX30_DSI_FORCETXSTOPMODE), 1491 + .lanecfg1 = FIELD_PREP_WM16_CONST((PX30_DSI_TURNDISABLE | 1492 + PX30_DSI_FORCERXMODE | 1493 + PX30_DSI_FORCETXSTOPMODE), 0), 1494 1494 1495 1495 .max_data_lanes = 4, 1496 1496 }, ··· 1500 1502 { 1501 1503 .reg = 0x10110000, 1502 1504 .lanecfg1_grf_reg = RK3128_GRF_LVDS_CON0, 1503 - .lanecfg1 = HIWORD_UPDATE(0, RK3128_DSI_TURNDISABLE | 1504 - RK3128_DSI_FORCERXMODE | 1505 - RK3128_DSI_FORCETXSTOPMODE), 1505 + .lanecfg1 = FIELD_PREP_WM16_CONST((RK3128_DSI_TURNDISABLE | 1506 + RK3128_DSI_FORCERXMODE | 1507 + RK3128_DSI_FORCETXSTOPMODE), 0), 1506 1508 .max_data_lanes = 4, 1507 1509 }, 1508 1510 { /* sentinel */ } ··· 1512 1514 { 1513 1515 .reg = 0xff960000, 1514 1516 .lcdsel_grf_reg = RK3288_GRF_SOC_CON6, 1515 - .lcdsel_big = HIWORD_UPDATE(0, RK3288_DSI0_LCDC_SEL), 1516 - .lcdsel_lit = HIWORD_UPDATE(RK3288_DSI0_LCDC_SEL, RK3288_DSI0_LCDC_SEL), 1517 + .lcdsel_big = FIELD_PREP_WM16_CONST(RK3288_DSI0_LCDC_SEL, 0), 1518 + .lcdsel_lit = FIELD_PREP_WM16_CONST(RK3288_DSI0_LCDC_SEL, 1), 1517 1519 1518 1520 .max_data_lanes = 4, 1519 1521 }, 1520 1522 { 1521 1523 .reg = 0xff964000, 1522 1524 .lcdsel_grf_reg = RK3288_GRF_SOC_CON6, 1523 - .lcdsel_big = HIWORD_UPDATE(0, RK3288_DSI1_LCDC_SEL), 1524 - .lcdsel_lit = HIWORD_UPDATE(RK3288_DSI1_LCDC_SEL, RK3288_DSI1_LCDC_SEL), 1525 + .lcdsel_big = FIELD_PREP_WM16_CONST(RK3288_DSI1_LCDC_SEL, 0), 1526 + .lcdsel_lit = FIELD_PREP_WM16_CONST(RK3288_DSI1_LCDC_SEL, 1), 1525 1527 1526 1528 .max_data_lanes = 4, 1527 1529 }, ··· 1537 1539 * Assume ISP0 is supplied by the RX0 dphy. 1538 1540 */ 1539 1541 regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24, 1540 - HIWORD_UPDATE(0, RK3399_TXRX_SRC_SEL_ISP0)); 1542 + FIELD_PREP_WM16(RK3399_TXRX_SRC_SEL_ISP0, 0)); 1541 1543 regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24, 1542 - HIWORD_UPDATE(0, RK3399_TXRX_MASTERSLAVEZ)); 1544 + FIELD_PREP_WM16(RK3399_TXRX_MASTERSLAVEZ, 0)); 1543 1545 regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24, 1544 - HIWORD_UPDATE(0, RK3399_TXRX_BASEDIR)); 1546 + FIELD_PREP_WM16(RK3399_TXRX_BASEDIR, 0)); 1545 1547 regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23, 1546 - HIWORD_UPDATE(0, RK3399_DSI1_ENABLE)); 1548 + FIELD_PREP_WM16(RK3399_DSI1_ENABLE, 0)); 1547 1549 1548 1550 return 0; 1549 1551 } ··· 1557 1559 usleep_range(100, 150); 1558 1560 1559 1561 regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24, 1560 - HIWORD_UPDATE(0, RK3399_TXRX_MASTERSLAVEZ)); 1562 + FIELD_PREP_WM16(RK3399_TXRX_MASTERSLAVEZ, 0)); 1561 1563 regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24, 1562 - HIWORD_UPDATE(RK3399_TXRX_BASEDIR, RK3399_TXRX_BASEDIR)); 1564 + FIELD_PREP_WM16(RK3399_TXRX_BASEDIR, 1)); 1563 1565 1564 1566 regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23, 1565 - HIWORD_UPDATE(0, RK3399_DSI1_FORCERXMODE)); 1567 + FIELD_PREP_WM16(RK3399_DSI1_FORCERXMODE, 0)); 1566 1568 regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23, 1567 - HIWORD_UPDATE(0, RK3399_DSI1_FORCETXSTOPMODE)); 1569 + FIELD_PREP_WM16(RK3399_DSI1_FORCETXSTOPMODE, 0)); 1568 1570 1569 1571 /* Disable lane turn around, which is ignored in receive mode */ 1570 1572 regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24, 1571 - HIWORD_UPDATE(0, RK3399_TXRX_TURNREQUEST)); 1573 + FIELD_PREP_WM16(RK3399_TXRX_TURNREQUEST, 0)); 1572 1574 regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23, 1573 - HIWORD_UPDATE(RK3399_DSI1_TURNDISABLE, 1574 - RK3399_DSI1_TURNDISABLE)); 1575 + FIELD_PREP_WM16(RK3399_DSI1_TURNDISABLE, 0xf)); 1575 1576 usleep_range(100, 150); 1576 1577 1577 1578 dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR); ··· 1578 1581 1579 1582 /* Enable dphy lanes */ 1580 1583 regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23, 1581 - HIWORD_UPDATE(GENMASK(dsi->dphy_config.lanes - 1, 0), 1582 - RK3399_DSI1_ENABLE)); 1584 + FIELD_PREP_WM16(RK3399_DSI1_ENABLE, 1585 + GENMASK(dsi->dphy_config.lanes - 1, 0))); 1583 1586 1584 1587 usleep_range(100, 150); 1585 1588 ··· 1591 1594 struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy); 1592 1595 1593 1596 regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23, 1594 - HIWORD_UPDATE(0, RK3399_DSI1_ENABLE)); 1597 + FIELD_PREP_WM16(RK3399_DSI1_ENABLE, 0)); 1595 1598 1596 1599 return 0; 1597 1600 } ··· 1600 1603 { 1601 1604 .reg = 0xff960000, 1602 1605 .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, 1603 - .lcdsel_big = HIWORD_UPDATE(0, RK3399_DSI0_LCDC_SEL), 1604 - .lcdsel_lit = HIWORD_UPDATE(RK3399_DSI0_LCDC_SEL, 1605 - RK3399_DSI0_LCDC_SEL), 1606 + .lcdsel_big = FIELD_PREP_WM16_CONST(RK3399_DSI0_LCDC_SEL, 0), 1607 + .lcdsel_lit = FIELD_PREP_WM16_CONST(RK3399_DSI0_LCDC_SEL, 1), 1606 1608 1607 1609 .lanecfg1_grf_reg = RK3399_GRF_SOC_CON22, 1608 - .lanecfg1 = HIWORD_UPDATE(0, RK3399_DSI0_TURNREQUEST | 1609 - RK3399_DSI0_TURNDISABLE | 1610 - RK3399_DSI0_FORCETXSTOPMODE | 1611 - RK3399_DSI0_FORCERXMODE), 1610 + .lanecfg1 = FIELD_PREP_WM16_CONST((RK3399_DSI0_TURNREQUEST | 1611 + RK3399_DSI0_TURNDISABLE | 1612 + RK3399_DSI0_FORCETXSTOPMODE | 1613 + RK3399_DSI0_FORCERXMODE), 0), 1612 1614 1613 1615 .flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK, 1614 1616 .max_data_lanes = 4, ··· 1615 1619 { 1616 1620 .reg = 0xff968000, 1617 1621 .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, 1618 - .lcdsel_big = HIWORD_UPDATE(0, RK3399_DSI1_LCDC_SEL), 1619 - .lcdsel_lit = HIWORD_UPDATE(RK3399_DSI1_LCDC_SEL, 1620 - RK3399_DSI1_LCDC_SEL), 1622 + .lcdsel_big = FIELD_PREP_WM16_CONST(RK3399_DSI1_LCDC_SEL, 0), 1623 + .lcdsel_lit = FIELD_PREP_WM16_CONST(RK3399_DSI1_LCDC_SEL, 1), 1624 + 1621 1625 1622 1626 .lanecfg1_grf_reg = RK3399_GRF_SOC_CON23, 1623 - .lanecfg1 = HIWORD_UPDATE(0, RK3399_DSI1_TURNDISABLE | 1624 - RK3399_DSI1_FORCETXSTOPMODE | 1625 - RK3399_DSI1_FORCERXMODE | 1626 - RK3399_DSI1_ENABLE), 1627 + .lanecfg1 = FIELD_PREP_WM16_CONST((RK3399_DSI1_TURNDISABLE | 1628 + RK3399_DSI1_FORCETXSTOPMODE | 1629 + RK3399_DSI1_FORCERXMODE | 1630 + RK3399_DSI1_ENABLE), 0), 1627 1631 1628 1632 .lanecfg2_grf_reg = RK3399_GRF_SOC_CON24, 1629 - .lanecfg2 = HIWORD_UPDATE(RK3399_TXRX_MASTERSLAVEZ | 1630 - RK3399_TXRX_ENABLECLK, 1631 - RK3399_TXRX_MASTERSLAVEZ | 1632 - RK3399_TXRX_ENABLECLK | 1633 - RK3399_TXRX_BASEDIR), 1633 + .lanecfg2 = (FIELD_PREP_WM16_CONST(RK3399_TXRX_MASTERSLAVEZ, 1) | 1634 + FIELD_PREP_WM16_CONST(RK3399_TXRX_ENABLECLK, 1) | 1635 + FIELD_PREP_WM16_CONST(RK3399_TXRX_BASEDIR, 0)), 1634 1636 1635 1637 .enable_grf_reg = RK3399_GRF_SOC_CON23, 1636 - .enable = HIWORD_UPDATE(RK3399_DSI1_ENABLE, RK3399_DSI1_ENABLE), 1638 + .enable = FIELD_PREP_WM16_CONST(RK3399_DSI1_ENABLE, RK3399_DSI1_ENABLE), 1637 1639 1638 1640 .flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK, 1639 1641 .max_data_lanes = 4, ··· 1647 1653 { 1648 1654 .reg = 0xfe060000, 1649 1655 .lanecfg1_grf_reg = RK3568_GRF_VO_CON2, 1650 - .lanecfg1 = HIWORD_UPDATE(0, RK3568_DSI0_SKEWCALHS | 1651 - RK3568_DSI0_FORCETXSTOPMODE | 1652 - RK3568_DSI0_TURNDISABLE | 1653 - RK3568_DSI0_FORCERXMODE), 1656 + .lanecfg1 = (FIELD_PREP_WM16_CONST(RK3568_DSI0_SKEWCALHS, 0) | 1657 + FIELD_PREP_WM16_CONST(RK3568_DSI0_FORCETXSTOPMODE, 0) | 1658 + FIELD_PREP_WM16_CONST(RK3568_DSI0_TURNDISABLE, 0) | 1659 + FIELD_PREP_WM16_CONST(RK3568_DSI0_FORCERXMODE, 0)), 1654 1660 .max_data_lanes = 4, 1655 1661 }, 1656 1662 { 1657 1663 .reg = 0xfe070000, 1658 1664 .lanecfg1_grf_reg = RK3568_GRF_VO_CON3, 1659 - .lanecfg1 = HIWORD_UPDATE(0, RK3568_DSI1_SKEWCALHS | 1660 - RK3568_DSI1_FORCETXSTOPMODE | 1661 - RK3568_DSI1_TURNDISABLE | 1662 - RK3568_DSI1_FORCERXMODE), 1665 + .lanecfg1 = (FIELD_PREP_WM16_CONST(RK3568_DSI1_SKEWCALHS, 0) | 1666 + FIELD_PREP_WM16_CONST(RK3568_DSI1_FORCETXSTOPMODE, 0) | 1667 + FIELD_PREP_WM16_CONST(RK3568_DSI1_TURNDISABLE, 0) | 1668 + FIELD_PREP_WM16_CONST(RK3568_DSI1_FORCERXMODE, 0)), 1663 1669 .max_data_lanes = 4, 1664 1670 }, 1665 1671 { /* sentinel */ } ··· 1669 1675 { 1670 1676 .reg = 0xffb30000, 1671 1677 .lanecfg1_grf_reg = RV1126_GRF_DSIPHY_CON, 1672 - .lanecfg1 = HIWORD_UPDATE(0, RV1126_DSI_TURNDISABLE | 1673 - RV1126_DSI_FORCERXMODE | 1674 - RV1126_DSI_FORCETXSTOPMODE), 1678 + .lanecfg1 = (FIELD_PREP_WM16_CONST(RV1126_DSI_TURNDISABLE, 0) | 1679 + FIELD_PREP_WM16_CONST(RV1126_DSI_FORCERXMODE, 0) | 1680 + FIELD_PREP_WM16_CONST(RV1126_DSI_FORCETXSTOPMODE, 0)), 1675 1681 .max_data_lanes = 4, 1676 1682 }, 1677 1683 { /* sentinel */ }
+35 -43
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
··· 4 4 */ 5 5 6 6 #include <linux/clk.h> 7 + #include <linux/hw_bitfield.h> 7 8 #include <linux/mfd/syscon.h> 8 9 #include <linux/module.h> 9 10 #include <linux/platform_device.h> ··· 54 53 #define RK3568_GRF_VO_CON1 0x0364 55 54 #define RK3568_HDMI_SDAIN_MSK BIT(15) 56 55 #define RK3568_HDMI_SCLIN_MSK BIT(14) 57 - 58 - #define HIWORD_UPDATE(val, mask) (val | (mask) << 16) 59 56 60 57 /** 61 58 * struct rockchip_hdmi_chip_data - splite the grf setting of kind of chips ··· 354 355 355 356 dw_hdmi_phy_setup_hpd(dw_hdmi, data); 356 357 357 - regmap_write(hdmi->regmap, 358 - RK3228_GRF_SOC_CON6, 359 - HIWORD_UPDATE(RK3228_HDMI_HPD_VSEL | RK3228_HDMI_SDA_VSEL | 360 - RK3228_HDMI_SCL_VSEL, 361 - RK3228_HDMI_HPD_VSEL | RK3228_HDMI_SDA_VSEL | 362 - RK3228_HDMI_SCL_VSEL)); 358 + regmap_write(hdmi->regmap, RK3228_GRF_SOC_CON6, 359 + FIELD_PREP_WM16(RK3228_HDMI_HPD_VSEL, 1) | 360 + FIELD_PREP_WM16(RK3228_HDMI_SDA_VSEL, 1) | 361 + FIELD_PREP_WM16(RK3228_HDMI_SCL_VSEL, 1)); 363 362 364 - regmap_write(hdmi->regmap, 365 - RK3228_GRF_SOC_CON2, 366 - HIWORD_UPDATE(RK3228_HDMI_SDAIN_MSK | RK3228_HDMI_SCLIN_MSK, 367 - RK3228_HDMI_SDAIN_MSK | RK3228_HDMI_SCLIN_MSK)); 363 + regmap_write(hdmi->regmap, RK3228_GRF_SOC_CON2, 364 + FIELD_PREP_WM16(RK3228_HDMI_SDAIN_MSK, 1) | 365 + FIELD_PREP_WM16(RK3328_HDMI_SCLIN_MSK, 1)); 368 366 } 369 367 370 368 static enum drm_connector_status ··· 373 377 status = dw_hdmi_phy_read_hpd(dw_hdmi, data); 374 378 375 379 if (status == connector_status_connected) 376 - regmap_write(hdmi->regmap, 377 - RK3328_GRF_SOC_CON4, 378 - HIWORD_UPDATE(RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V, 379 - RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V)); 380 + regmap_write(hdmi->regmap, RK3328_GRF_SOC_CON4, 381 + FIELD_PREP_WM16(RK3328_HDMI_SDA_5V, 1) | 382 + FIELD_PREP_WM16(RK3328_HDMI_SCL_5V, 1)); 380 383 else 381 - regmap_write(hdmi->regmap, 382 - RK3328_GRF_SOC_CON4, 383 - HIWORD_UPDATE(0, RK3328_HDMI_SDA_5V | 384 - RK3328_HDMI_SCL_5V)); 384 + regmap_write(hdmi->regmap, RK3328_GRF_SOC_CON4, 385 + FIELD_PREP_WM16(RK3328_HDMI_SDA_5V, 0) | 386 + FIELD_PREP_WM16(RK3328_HDMI_SCL_5V, 0)); 385 387 return status; 386 388 } 387 389 ··· 390 396 dw_hdmi_phy_setup_hpd(dw_hdmi, data); 391 397 392 398 /* Enable and map pins to 3V grf-controlled io-voltage */ 393 - regmap_write(hdmi->regmap, 394 - RK3328_GRF_SOC_CON4, 395 - HIWORD_UPDATE(0, RK3328_HDMI_HPD_SARADC | RK3328_HDMI_CEC_5V | 396 - RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V | 397 - RK3328_HDMI_HPD_5V)); 398 - regmap_write(hdmi->regmap, 399 - RK3328_GRF_SOC_CON3, 400 - HIWORD_UPDATE(0, RK3328_HDMI_SDA5V_GRF | RK3328_HDMI_SCL5V_GRF | 401 - RK3328_HDMI_HPD5V_GRF | 402 - RK3328_HDMI_CEC5V_GRF)); 403 - regmap_write(hdmi->regmap, 404 - RK3328_GRF_SOC_CON2, 405 - HIWORD_UPDATE(RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK, 406 - RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK | 407 - RK3328_HDMI_HPD_IOE)); 399 + regmap_write(hdmi->regmap, RK3328_GRF_SOC_CON4, 400 + FIELD_PREP_WM16(RK3328_HDMI_HPD_SARADC, 0) | 401 + FIELD_PREP_WM16(RK3328_HDMI_CEC_5V, 0) | 402 + FIELD_PREP_WM16(RK3328_HDMI_SDA_5V, 0) | 403 + FIELD_PREP_WM16(RK3328_HDMI_SCL_5V, 0) | 404 + FIELD_PREP_WM16(RK3328_HDMI_HPD_5V, 0)); 405 + regmap_write(hdmi->regmap, RK3328_GRF_SOC_CON3, 406 + FIELD_PREP_WM16(RK3328_HDMI_SDA5V_GRF, 0) | 407 + FIELD_PREP_WM16(RK3328_HDMI_SCL5V_GRF, 0) | 408 + FIELD_PREP_WM16(RK3328_HDMI_HPD5V_GRF, 0) | 409 + FIELD_PREP_WM16(RK3328_HDMI_CEC5V_GRF, 0)); 410 + regmap_write(hdmi->regmap, RK3328_GRF_SOC_CON2, 411 + FIELD_PREP_WM16(RK3328_HDMI_SDAIN_MSK, 1) | 412 + FIELD_PREP_WM16(RK3328_HDMI_SCLIN_MSK, 1) | 413 + FIELD_PREP_WM16(RK3328_HDMI_HPD_IOE, 0)); 408 414 409 415 dw_hdmi_rk3328_read_hpd(dw_hdmi, data); 410 416 } ··· 432 438 433 439 static struct rockchip_hdmi_chip_data rk3288_chip_data = { 434 440 .lcdsel_grf_reg = RK3288_GRF_SOC_CON6, 435 - .lcdsel_big = HIWORD_UPDATE(0, RK3288_HDMI_LCDC_SEL), 436 - .lcdsel_lit = HIWORD_UPDATE(RK3288_HDMI_LCDC_SEL, RK3288_HDMI_LCDC_SEL), 441 + .lcdsel_big = FIELD_PREP_WM16_CONST(RK3288_HDMI_LCDC_SEL, 0), 442 + .lcdsel_lit = FIELD_PREP_WM16_CONST(RK3288_HDMI_LCDC_SEL, 1), 437 443 .max_tmds_clock = 340000, 438 444 }; 439 445 ··· 469 475 470 476 static struct rockchip_hdmi_chip_data rk3399_chip_data = { 471 477 .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, 472 - .lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL), 473 - .lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL), 478 + .lcdsel_big = FIELD_PREP_WM16_CONST(RK3399_HDMI_LCDC_SEL, 0), 479 + .lcdsel_lit = FIELD_PREP_WM16_CONST(RK3399_HDMI_LCDC_SEL, 1), 474 480 .max_tmds_clock = 594000, 475 481 }; 476 482 ··· 583 589 584 590 if (hdmi->chip_data == &rk3568_chip_data) { 585 591 regmap_write(hdmi->regmap, RK3568_GRF_VO_CON1, 586 - HIWORD_UPDATE(RK3568_HDMI_SDAIN_MSK | 587 - RK3568_HDMI_SCLIN_MSK, 588 - RK3568_HDMI_SDAIN_MSK | 589 - RK3568_HDMI_SCLIN_MSK)); 592 + FIELD_PREP_WM16(RK3568_HDMI_SDAIN_MSK, 1) | 593 + FIELD_PREP_WM16(RK3568_HDMI_SCLIN_MSK, 1)); 590 594 } 591 595 592 596 drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
+33 -35
drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
··· 9 9 10 10 #include <linux/clk.h> 11 11 #include <linux/gpio/consumer.h> 12 + #include <linux/hw_bitfield.h> 12 13 #include <linux/mfd/syscon.h> 13 14 #include <linux/module.h> 14 15 #include <linux/platform_device.h> ··· 67 66 #define RK3588_HDMI1_HPD_INT_MSK BIT(15) 68 67 #define RK3588_HDMI1_HPD_INT_CLR BIT(14) 69 68 #define RK3588_GRF_SOC_CON7 0x031c 70 - #define RK3588_SET_HPD_PATH_MASK GENMASK(13, 12) 69 + #define RK3588_HPD_HDMI0_IO_EN_MASK BIT(12) 70 + #define RK3588_HPD_HDMI1_IO_EN_MASK BIT(13) 71 71 #define RK3588_GRF_SOC_STATUS1 0x0384 72 72 #define RK3588_HDMI0_LEVEL_INT BIT(16) 73 73 #define RK3588_HDMI1_LEVEL_INT BIT(24) ··· 82 80 #define RK3588_HDMI0_GRANT_SEL BIT(10) 83 81 #define RK3588_HDMI1_GRANT_SEL BIT(12) 84 82 85 - #define HIWORD_UPDATE(val, mask) ((val) | (mask) << 16) 86 83 #define HOTPLUG_DEBOUNCE_MS 150 87 84 #define MAX_HDMI_PORT_NUM 2 88 85 ··· 186 185 u32 val; 187 186 188 187 if (hdmi->port_id) 189 - val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_CLR, 190 - RK3588_HDMI1_HPD_INT_CLR | RK3588_HDMI1_HPD_INT_MSK); 188 + val = (FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_CLR, 1) | 189 + FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_MSK, 0)); 191 190 else 192 - val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR, 193 - RK3588_HDMI0_HPD_INT_CLR | RK3588_HDMI0_HPD_INT_MSK); 191 + val = (FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_CLR, 1) | 192 + FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_MSK, 0)); 194 193 195 194 regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); 196 195 } ··· 219 218 struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data; 220 219 u32 val; 221 220 222 - val = HIWORD_UPDATE(RK3576_HDMI_HPD_INT_CLR, 223 - RK3576_HDMI_HPD_INT_CLR | RK3576_HDMI_HPD_INT_MSK); 221 + val = (FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_CLR, 1) | 222 + FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_MSK, 0)); 224 223 225 224 regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val); 226 225 regmap_write(hdmi->regmap, 0xa404, 0xffff0102); ··· 255 254 256 255 regmap_read(hdmi->regmap, RK3576_IOC_HDMI_HPD_STATUS, &intr_stat); 257 256 if (intr_stat) { 258 - val = HIWORD_UPDATE(RK3576_HDMI_HPD_INT_MSK, RK3576_HDMI_HPD_INT_MSK); 257 + val = FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_MSK, 1); 259 258 260 259 regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val); 261 260 return IRQ_WAKE_THREAD; ··· 274 273 if (!intr_stat) 275 274 return IRQ_NONE; 276 275 277 - val = HIWORD_UPDATE(RK3576_HDMI_HPD_INT_CLR, RK3576_HDMI_HPD_INT_CLR); 276 + val = FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_CLR, 1); 278 277 regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val); 279 278 mod_delayed_work(system_wq, &hdmi->hpd_work, 280 279 msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS)); 281 280 282 - val = HIWORD_UPDATE(0, RK3576_HDMI_HPD_INT_MSK); 281 + val = FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_MSK, 0); 283 282 regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val); 284 283 285 284 return IRQ_HANDLED; ··· 294 293 295 294 if (intr_stat) { 296 295 if (hdmi->port_id) 297 - val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_MSK, 298 - RK3588_HDMI1_HPD_INT_MSK); 296 + val = FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_MSK, 1); 299 297 else 300 - val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK, 301 - RK3588_HDMI0_HPD_INT_MSK); 298 + val = FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_MSK, 1); 302 299 regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); 303 300 return IRQ_WAKE_THREAD; 304 301 } ··· 314 315 return IRQ_NONE; 315 316 316 317 if (hdmi->port_id) 317 - val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_CLR, 318 - RK3588_HDMI1_HPD_INT_CLR); 318 + val = FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_CLR, 1); 319 319 else 320 - val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR, 321 - RK3588_HDMI0_HPD_INT_CLR); 320 + val = FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_CLR, 1); 322 321 regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); 323 322 324 323 mod_delayed_work(system_wq, &hdmi->hpd_work, 325 324 msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS)); 326 325 327 326 if (hdmi->port_id) 328 - val |= HIWORD_UPDATE(0, RK3588_HDMI1_HPD_INT_MSK); 327 + val |= FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_MSK, 0); 329 328 else 330 - val |= HIWORD_UPDATE(0, RK3588_HDMI0_HPD_INT_MSK); 329 + val |= FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_MSK, 0); 331 330 regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); 332 331 333 332 return IRQ_HANDLED; ··· 335 338 { 336 339 u32 val; 337 340 338 - val = HIWORD_UPDATE(RK3576_SCLIN_MASK, RK3576_SCLIN_MASK) | 339 - HIWORD_UPDATE(RK3576_SDAIN_MASK, RK3576_SDAIN_MASK) | 340 - HIWORD_UPDATE(RK3576_HDMI_GRANT_SEL, RK3576_HDMI_GRANT_SEL) | 341 - HIWORD_UPDATE(RK3576_I2S_SEL_MASK, RK3576_I2S_SEL_MASK); 341 + val = FIELD_PREP_WM16(RK3576_SCLIN_MASK, 1) | 342 + FIELD_PREP_WM16(RK3576_SDAIN_MASK, 1) | 343 + FIELD_PREP_WM16(RK3576_HDMI_GRANT_SEL, 1) | 344 + FIELD_PREP_WM16(RK3576_I2S_SEL_MASK, 1); 342 345 343 346 regmap_write(hdmi->vo_regmap, RK3576_VO0_GRF_SOC_CON14, val); 344 347 345 - val = HIWORD_UPDATE(0, RK3576_HDMI_HPD_INT_MSK); 348 + val = FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_MSK, 0); 346 349 regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val); 347 350 } 348 351 ··· 350 353 { 351 354 u32 val; 352 355 353 - val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) | 354 - HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) | 355 - HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) | 356 - HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK); 356 + val = FIELD_PREP_WM16(RK3588_SCLIN_MASK, 1) | 357 + FIELD_PREP_WM16(RK3588_SDAIN_MASK, 1) | 358 + FIELD_PREP_WM16(RK3588_MODE_MASK, 1) | 359 + FIELD_PREP_WM16(RK3588_I2S_SEL_MASK, 1); 357 360 regmap_write(hdmi->vo_regmap, 358 361 hdmi->port_id ? RK3588_GRF_VO1_CON6 : RK3588_GRF_VO1_CON3, 359 362 val); 360 363 361 - val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK, RK3588_SET_HPD_PATH_MASK); 364 + val = FIELD_PREP_WM16(RK3588_HPD_HDMI0_IO_EN_MASK, 1) | 365 + FIELD_PREP_WM16(RK3588_HPD_HDMI1_IO_EN_MASK, 1); 362 366 regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val); 363 367 364 368 if (hdmi->port_id) 365 - val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL, RK3588_HDMI1_GRANT_SEL); 369 + val = FIELD_PREP_WM16(RK3588_HDMI1_GRANT_SEL, 1); 366 370 else 367 - val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL, RK3588_HDMI0_GRANT_SEL); 371 + val = FIELD_PREP_WM16(RK3588_HDMI0_GRANT_SEL, 1); 368 372 regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON9, val); 369 373 370 374 if (hdmi->port_id) 371 - val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_MSK, RK3588_HDMI1_HPD_INT_MSK); 375 + val = FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_MSK, 1); 372 376 else 373 - val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK, RK3588_HDMI0_HPD_INT_MSK); 377 + val = FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_MSK, 1); 374 378 regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); 375 379 } 376 380
+5 -6
drivers/gpu/drm/rockchip/inno_hdmi.c
··· 10 10 #include <linux/delay.h> 11 11 #include <linux/err.h> 12 12 #include <linux/hdmi.h> 13 + #include <linux/hw_bitfield.h> 13 14 #include <linux/mfd/syscon.h> 14 15 #include <linux/mod_devicetable.h> 15 16 #include <linux/module.h> ··· 382 381 #define HDMI_CEC_BUSFREETIME_L 0xdc 383 382 #define HDMI_CEC_BUSFREETIME_H 0xdd 384 383 #define HDMI_CEC_LOGICADDR 0xde 385 - 386 - #define HIWORD_UPDATE(val, mask) ((val) | (mask) << 16) 387 384 388 385 #define RK3036_GRF_SOC_CON2 0x148 389 386 #define RK3036_HDMI_PHSYNC BIT(4) ··· 755 756 int value, psync; 756 757 757 758 if (hdmi->variant->dev_type == RK3036_HDMI) { 758 - psync = mode->flags & DRM_MODE_FLAG_PHSYNC ? RK3036_HDMI_PHSYNC : 0; 759 - value = HIWORD_UPDATE(psync, RK3036_HDMI_PHSYNC); 760 - psync = mode->flags & DRM_MODE_FLAG_PVSYNC ? RK3036_HDMI_PVSYNC : 0; 761 - value |= HIWORD_UPDATE(psync, RK3036_HDMI_PVSYNC); 759 + psync = mode->flags & DRM_MODE_FLAG_PHSYNC ? 1 : 0; 760 + value = FIELD_PREP_WM16(RK3036_HDMI_PHSYNC, psync); 761 + psync = mode->flags & DRM_MODE_FLAG_PVSYNC ? 1 : 0; 762 + value |= FIELD_PREP_WM16(RK3036_HDMI_PVSYNC, psync); 762 763 regmap_write(hdmi->grf, RK3036_GRF_SOC_CON2, value); 763 764 } 764 765
-1
drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
··· 33 33 #define WIN_FEATURE_AFBDC BIT(0) 34 34 #define WIN_FEATURE_CLUSTER BIT(1) 35 35 36 - #define HIWORD_UPDATE(v, h, l) ((GENMASK(h, l) << 16) | ((v) << (l))) 37 36 /* 38 37 * the delay number of a window in different mode. 39 38 */
+11 -10
drivers/gpu/drm/rockchip/rockchip_lvds.h
··· 9 9 #ifndef _ROCKCHIP_LVDS_ 10 10 #define _ROCKCHIP_LVDS_ 11 11 12 + #include <linux/bits.h> 13 + #include <linux/hw_bitfield.h> 14 + 12 15 #define RK3288_LVDS_CH0_REG0 0x00 13 16 #define RK3288_LVDS_CH0_REG0_LVDS_EN BIT(7) 14 17 #define RK3288_LVDS_CH0_REG0_TTL_EN BIT(6) ··· 109 106 #define LVDS_VESA_18 2 110 107 #define LVDS_JEIDA_18 3 111 108 112 - #define HIWORD_UPDATE(v, h, l) ((GENMASK(h, l) << 16) | ((v) << (l))) 113 - 114 109 #define PX30_LVDS_GRF_PD_VO_CON0 0x434 115 - #define PX30_LVDS_TIE_CLKS(val) HIWORD_UPDATE(val, 8, 8) 116 - #define PX30_LVDS_INVERT_CLKS(val) HIWORD_UPDATE(val, 9, 9) 117 - #define PX30_LVDS_INVERT_DCLK(val) HIWORD_UPDATE(val, 5, 5) 110 + #define PX30_LVDS_TIE_CLKS(val) FIELD_PREP_WM16(BIT(8), (val)) 111 + #define PX30_LVDS_INVERT_CLKS(val) FIELD_PREP_WM16(BIT(9), (val)) 112 + #define PX30_LVDS_INVERT_DCLK(val) FIELD_PREP_WM16(BIT(5), (val)) 118 113 119 114 #define PX30_LVDS_GRF_PD_VO_CON1 0x438 120 - #define PX30_LVDS_FORMAT(val) HIWORD_UPDATE(val, 14, 13) 121 - #define PX30_LVDS_MODE_EN(val) HIWORD_UPDATE(val, 12, 12) 122 - #define PX30_LVDS_MSBSEL(val) HIWORD_UPDATE(val, 11, 11) 123 - #define PX30_LVDS_P2S_EN(val) HIWORD_UPDATE(val, 6, 6) 124 - #define PX30_LVDS_VOP_SEL(val) HIWORD_UPDATE(val, 1, 1) 115 + #define PX30_LVDS_FORMAT(val) FIELD_PREP_WM16(GENMASK(14, 13), (val)) 116 + #define PX30_LVDS_MODE_EN(val) FIELD_PREP_WM16(BIT(12), (val)) 117 + #define PX30_LVDS_MSBSEL(val) FIELD_PREP_WM16(BIT(11), (val)) 118 + #define PX30_LVDS_P2S_EN(val) FIELD_PREP_WM16(BIT(6), (val)) 119 + #define PX30_LVDS_VOP_SEL(val) FIELD_PREP_WM16(BIT(1), (val)) 125 120 126 121 #endif /* _ROCKCHIP_LVDS_ */
+9 -6
drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
··· 7 7 #include <linux/bitfield.h> 8 8 #include <linux/kernel.h> 9 9 #include <linux/component.h> 10 + #include <linux/hw_bitfield.h> 10 11 #include <linux/mod_devicetable.h> 11 12 #include <linux/platform_device.h> 12 13 #include <linux/of.h> ··· 1696 1695 die |= RK3588_SYS_DSP_INFACE_EN_HDMI0 | 1697 1696 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id); 1698 1697 val = rk3588_get_hdmi_pol(polflags); 1699 - regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 1, 1)); 1700 - regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0, HIWORD_UPDATE(val, 6, 5)); 1698 + regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, FIELD_PREP_WM16(BIT(1), 1)); 1699 + regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0, 1700 + FIELD_PREP_WM16(GENMASK(6, 5), val)); 1701 1701 break; 1702 1702 case ROCKCHIP_VOP2_EP_HDMI1: 1703 1703 div &= ~RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV; ··· 1709 1707 die |= RK3588_SYS_DSP_INFACE_EN_HDMI1 | 1710 1708 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id); 1711 1709 val = rk3588_get_hdmi_pol(polflags); 1712 - regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 4, 4)); 1713 - regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0, HIWORD_UPDATE(val, 8, 7)); 1710 + regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, FIELD_PREP_WM16(BIT(4), 1)); 1711 + regmap_write(vop2->vo1_grf, RK3588_GRF_VO1_CON0, 1712 + FIELD_PREP_WM16(GENMASK(8, 7), val)); 1714 1713 break; 1715 1714 case ROCKCHIP_VOP2_EP_EDP0: 1716 1715 div &= ~RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV; ··· 1721 1718 die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX; 1722 1719 die |= RK3588_SYS_DSP_INFACE_EN_EDP0 | 1723 1720 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX, vp->id); 1724 - regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 0, 0)); 1721 + regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, FIELD_PREP_WM16(BIT(0), 1)); 1725 1722 break; 1726 1723 case ROCKCHIP_VOP2_EP_EDP1: 1727 1724 div &= ~RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV; ··· 1731 1728 die &= ~RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX; 1732 1729 die |= RK3588_SYS_DSP_INFACE_EN_EDP1 | 1733 1730 FIELD_PREP(RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX, vp->id); 1734 - regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, HIWORD_UPDATE(1, 3, 3)); 1731 + regmap_write(vop2->vop_grf, RK3588_GRF_VOP_CON2, FIELD_PREP_WM16(BIT(3), 1)); 1735 1732 break; 1736 1733 case ROCKCHIP_VOP2_EP_MIPI0: 1737 1734 div &= ~RK3588_DSP_IF_MIPI0_PCLK_DIV;
+4 -2
drivers/media/platform/synopsys/hdmirx/snps_hdmirx.h
··· 8 8 #ifndef DW_HDMIRX_H 9 9 #define DW_HDMIRX_H 10 10 11 + #include <linux/bitfield.h> 11 12 #include <linux/bitops.h> 13 + #include <linux/hw_bitfield.h> 12 14 13 - #define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l))) 14 - #define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK((h), (l)) << 16)) 15 + #define UPDATE(x, h, l) FIELD_PREP(GENMASK((h), (l)), (x)) 16 + #define HIWORD_UPDATE(v, h, l) FIELD_PREP_WM16(GENMASK((h), (l)), (v)) 15 17 16 18 /* SYS_GRF */ 17 19 #define SYS_GRF_SOC_CON1 0x0304
+5 -4
drivers/mmc/host/dw_mmc-rockchip.c
··· 6 6 #include <linux/module.h> 7 7 #include <linux/platform_device.h> 8 8 #include <linux/clk.h> 9 + #include <linux/hw_bitfield.h> 9 10 #include <linux/mmc/host.h> 10 11 #include <linux/of_address.h> 11 12 #include <linux/mmc/slot-gpio.h> ··· 25 24 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2 26 25 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) 27 26 #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 28 - #define HIWORD_UPDATE(val, mask, shift) \ 29 - ((val) << (shift) | (mask) << ((shift) + 16)) 30 27 31 28 static const unsigned int freqs[] = { 100000, 200000, 300000, 400000 }; 32 29 ··· 147 148 raw_value |= nineties; 148 149 149 150 if (sample) 150 - mci_writel(host, TIMING_CON1, HIWORD_UPDATE(raw_value, 0x07ff, 1)); 151 + mci_writel(host, TIMING_CON1, 152 + FIELD_PREP_WM16(GENMASK(11, 1), raw_value)); 151 153 else 152 - mci_writel(host, TIMING_CON0, HIWORD_UPDATE(raw_value, 0x07ff, 1)); 154 + mci_writel(host, TIMING_CON0, 155 + FIELD_PREP_WM16(GENMASK(11, 1), raw_value)); 153 156 154 157 dev_dbg(host->dev, "set %s_phase(%d) delay_nums=%u actual_degrees=%d\n", 155 158 sample ? "sample" : "drv", degrees, delay_num,
+2 -1
drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
··· 8 8 */ 9 9 10 10 #include <linux/stmmac.h> 11 + #include <linux/hw_bitfield.h> 11 12 #include <linux/bitops.h> 12 13 #include <linux/clk.h> 13 14 #include <linux/phy.h> ··· 151 150 } 152 151 153 152 #define HIWORD_UPDATE(val, mask, shift) \ 154 - ((val) << (shift) | (mask) << ((shift) + 16)) 153 + (FIELD_PREP_WM16((mask) << (shift), (val))) 155 154 156 155 #define GRF_BIT(nr) (BIT(nr) | BIT(nr+16)) 157 156 #define GRF_CLR_BIT(nr) (BIT(nr+16))
+26 -16
drivers/pci/controller/dwc/pcie-dw-rockchip.c
··· 11 11 #include <linux/bitfield.h> 12 12 #include <linux/clk.h> 13 13 #include <linux/gpio/consumer.h> 14 + #include <linux/hw_bitfield.h> 14 15 #include <linux/irqchip/chained_irq.h> 15 16 #include <linux/irqdomain.h> 16 17 #include <linux/mfd/syscon.h> ··· 30 29 * The upper 16 bits of PCIE_CLIENT_CONFIG are a write 31 30 * mask for the lower 16 bits. 32 31 */ 33 - #define HIWORD_UPDATE(mask, val) (((mask) << 16) | (val)) 34 - #define HIWORD_UPDATE_BIT(val) HIWORD_UPDATE(val, val) 35 - #define HIWORD_DISABLE_BIT(val) HIWORD_UPDATE(val, ~val) 36 32 37 33 #define to_rockchip_pcie(x) dev_get_drvdata((x)->dev) 38 34 39 35 /* General Control Register */ 40 36 #define PCIE_CLIENT_GENERAL_CON 0x0 41 - #define PCIE_CLIENT_RC_MODE HIWORD_UPDATE_BIT(0x40) 42 - #define PCIE_CLIENT_EP_MODE HIWORD_UPDATE(0xf0, 0x0) 43 - #define PCIE_CLIENT_ENABLE_LTSSM HIWORD_UPDATE_BIT(0xc) 44 - #define PCIE_CLIENT_DISABLE_LTSSM HIWORD_UPDATE(0x0c, 0x8) 37 + #define PCIE_CLIENT_MODE_MASK GENMASK(7, 4) 38 + #define PCIE_CLIENT_MODE_EP 0x0UL 39 + #define PCIE_CLIENT_MODE_RC 0x4UL 40 + #define PCIE_CLIENT_SET_MODE(x) FIELD_PREP_WM16(PCIE_CLIENT_MODE_MASK, (x)) 41 + #define PCIE_CLIENT_LD_RQ_RST_GRT FIELD_PREP_WM16(BIT(3), 1) 42 + #define PCIE_CLIENT_ENABLE_LTSSM FIELD_PREP_WM16(BIT(2), 1) 43 + #define PCIE_CLIENT_DISABLE_LTSSM FIELD_PREP_WM16(BIT(2), 0) 45 44 46 45 /* Interrupt Status Register Related to Legacy Interrupt */ 47 46 #define PCIE_CLIENT_INTR_STATUS_LEGACY 0x8 ··· 53 52 54 53 /* Interrupt Mask Register Related to Legacy Interrupt */ 55 54 #define PCIE_CLIENT_INTR_MASK_LEGACY 0x1c 55 + #define PCIE_INTR_MASK GENMASK(7, 0) 56 + #define PCIE_INTR_CLAMP(_x) ((BIT((_x)) & PCIE_INTR_MASK)) 57 + #define PCIE_INTR_LEGACY_MASK(x) (PCIE_INTR_CLAMP((x)) | \ 58 + (PCIE_INTR_CLAMP((x)) << 16)) 59 + #define PCIE_INTR_LEGACY_UNMASK(x) (PCIE_INTR_CLAMP((x)) << 16) 56 60 57 61 /* Interrupt Mask Register Related to Miscellaneous Operation */ 58 62 #define PCIE_CLIENT_INTR_MASK_MISC 0x24 ··· 122 116 static void rockchip_intx_mask(struct irq_data *data) 123 117 { 124 118 rockchip_pcie_writel_apb(irq_data_get_irq_chip_data(data), 125 - HIWORD_UPDATE_BIT(BIT(data->hwirq)), 119 + PCIE_INTR_LEGACY_MASK(data->hwirq), 126 120 PCIE_CLIENT_INTR_MASK_LEGACY); 127 121 }; 128 122 129 123 static void rockchip_intx_unmask(struct irq_data *data) 130 124 { 131 125 rockchip_pcie_writel_apb(irq_data_get_irq_chip_data(data), 132 - HIWORD_DISABLE_BIT(BIT(data->hwirq)), 126 + PCIE_INTR_LEGACY_UNMASK(data->hwirq), 133 127 PCIE_CLIENT_INTR_MASK_LEGACY); 134 128 }; 135 129 ··· 495 489 dev_dbg(dev, "hot reset or link-down reset\n"); 496 490 dw_pcie_ep_linkdown(&pci->ep); 497 491 /* Stop delaying link training. */ 498 - val = HIWORD_UPDATE_BIT(PCIE_LTSSM_APP_DLY2_DONE); 492 + val = FIELD_PREP_WM16(PCIE_LTSSM_APP_DLY2_DONE, 1); 499 493 rockchip_pcie_writel_apb(rockchip, val, 500 494 PCIE_CLIENT_HOT_RESET_CTRL); 501 495 } ··· 534 528 } 535 529 536 530 /* LTSSM enable control mode */ 537 - val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE); 531 + val = FIELD_PREP_WM16(PCIE_LTSSM_ENABLE_ENHANCE, 1); 538 532 rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL); 539 533 540 - rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_RC_MODE, 534 + rockchip_pcie_writel_apb(rockchip, 535 + PCIE_CLIENT_SET_MODE(PCIE_CLIENT_MODE_RC), 541 536 PCIE_CLIENT_GENERAL_CON); 542 537 543 538 pp = &rockchip->pci.pp; ··· 552 545 } 553 546 554 547 /* unmask DLL up/down indicator */ 555 - val = HIWORD_UPDATE(PCIE_RDLH_LINK_UP_CHGED, 0); 548 + val = FIELD_PREP_WM16(PCIE_RDLH_LINK_UP_CHGED, 0); 556 549 rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_INTR_MASK_MISC); 557 550 558 551 return ret; ··· 584 577 * LTSSM enable control mode, and automatically delay link training on 585 578 * hot reset/link-down reset. 586 579 */ 587 - val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE | PCIE_LTSSM_APP_DLY2_EN); 580 + val = FIELD_PREP_WM16(PCIE_LTSSM_ENABLE_ENHANCE, 1) | 581 + FIELD_PREP_WM16(PCIE_LTSSM_APP_DLY2_EN, 1); 588 582 rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL); 589 583 590 - rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_EP_MODE, 584 + rockchip_pcie_writel_apb(rockchip, 585 + PCIE_CLIENT_SET_MODE(PCIE_CLIENT_MODE_EP), 591 586 PCIE_CLIENT_GENERAL_CON); 592 587 593 588 rockchip->pci.ep.ops = &rockchip_pcie_ep_ops; ··· 613 604 pci_epc_init_notify(rockchip->pci.ep.epc); 614 605 615 606 /* unmask DLL up/down indicator and hot reset/link-down reset */ 616 - val = HIWORD_UPDATE(PCIE_RDLH_LINK_UP_CHGED | PCIE_LINK_REQ_RST_NOT_INT, 0); 607 + val = FIELD_PREP_WM16(PCIE_RDLH_LINK_UP_CHGED, 0) | 608 + FIELD_PREP_WM16(PCIE_LINK_REQ_RST_NOT_INT, 0); 617 609 rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_INTR_MASK_MISC); 618 610 619 611 return ret;
+18 -17
drivers/pci/controller/pcie-rockchip.h
··· 12 12 #define _PCIE_ROCKCHIP_H 13 13 14 14 #include <linux/clk.h> 15 + #include <linux/hw_bitfield.h> 15 16 #include <linux/kernel.h> 16 17 #include <linux/pci.h> 17 18 #include <linux/pci-ecam.h> ··· 22 21 * The upper 16 bits of PCIE_CLIENT_CONFIG are a write mask for the lower 16 23 22 * bits. This allows atomic updates of the register without locking. 24 23 */ 25 - #define HIWORD_UPDATE(mask, val) (((mask) << 16) | (val)) 26 - #define HIWORD_UPDATE_BIT(val) HIWORD_UPDATE(val, val) 24 + #define HWORD_SET_BIT(val) (FIELD_PREP_WM16_CONST((val), 1)) 25 + #define HWORD_CLR_BIT(val) (FIELD_PREP_WM16_CONST((val), 0)) 27 26 28 - #define ENCODE_LANES(x) ((((x) >> 1) & 3) << 4) 27 + #define ENCODE_LANES(x) ((((x) >> 1) & 3)) 29 28 #define MAX_LANE_NUM 4 30 29 #define MAX_REGION_LIMIT 32 31 30 #define MIN_EP_APERTURE 28 ··· 33 32 34 33 #define PCIE_CLIENT_BASE 0x0 35 34 #define PCIE_CLIENT_CONFIG (PCIE_CLIENT_BASE + 0x00) 36 - #define PCIE_CLIENT_CONF_ENABLE HIWORD_UPDATE_BIT(0x0001) 37 - #define PCIE_CLIENT_CONF_DISABLE HIWORD_UPDATE(0x0001, 0) 38 - #define PCIE_CLIENT_LINK_TRAIN_ENABLE HIWORD_UPDATE_BIT(0x0002) 39 - #define PCIE_CLIENT_LINK_TRAIN_DISABLE HIWORD_UPDATE(0x0002, 0) 40 - #define PCIE_CLIENT_ARI_ENABLE HIWORD_UPDATE_BIT(0x0008) 41 - #define PCIE_CLIENT_CONF_LANE_NUM(x) HIWORD_UPDATE(0x0030, ENCODE_LANES(x)) 42 - #define PCIE_CLIENT_MODE_RC HIWORD_UPDATE_BIT(0x0040) 43 - #define PCIE_CLIENT_MODE_EP HIWORD_UPDATE(0x0040, 0) 44 - #define PCIE_CLIENT_GEN_SEL_1 HIWORD_UPDATE(0x0080, 0) 45 - #define PCIE_CLIENT_GEN_SEL_2 HIWORD_UPDATE_BIT(0x0080) 35 + #define PCIE_CLIENT_CONF_ENABLE HWORD_SET_BIT(0x0001) 36 + #define PCIE_CLIENT_CONF_DISABLE HWORD_CLR_BIT(0x0001) 37 + #define PCIE_CLIENT_LINK_TRAIN_ENABLE HWORD_SET_BIT(0x0002) 38 + #define PCIE_CLIENT_LINK_TRAIN_DISABLE HWORD_CLR_BIT(0x0002) 39 + #define PCIE_CLIENT_ARI_ENABLE HWORD_SET_BIT(0x0008) 40 + #define PCIE_CLIENT_CONF_LANE_NUM(x) FIELD_PREP_WM16(0x0030, ENCODE_LANES(x)) 41 + #define PCIE_CLIENT_MODE_RC HWORD_SET_BIT(0x0040) 42 + #define PCIE_CLIENT_MODE_EP HWORD_CLR_BIT(0x0040) 43 + #define PCIE_CLIENT_GEN_SEL_1 HWORD_CLR_BIT(0x0080) 44 + #define PCIE_CLIENT_GEN_SEL_2 HWORD_SET_BIT(0x0080) 46 45 #define PCIE_CLIENT_LEGACY_INT_CTRL (PCIE_CLIENT_BASE + 0x0c) 47 - #define PCIE_CLIENT_INT_IN_ASSERT HIWORD_UPDATE_BIT(0x0002) 48 - #define PCIE_CLIENT_INT_IN_DEASSERT HIWORD_UPDATE(0x0002, 0) 49 - #define PCIE_CLIENT_INT_PEND_ST_PEND HIWORD_UPDATE_BIT(0x0001) 50 - #define PCIE_CLIENT_INT_PEND_ST_NORMAL HIWORD_UPDATE(0x0001, 0) 46 + #define PCIE_CLIENT_INT_IN_ASSERT HWORD_SET_BIT(0x0002) 47 + #define PCIE_CLIENT_INT_IN_DEASSERT HWORD_CLR_BIT(0x0002) 48 + #define PCIE_CLIENT_INT_PEND_ST_PEND HWORD_SET_BIT(0x0001) 49 + #define PCIE_CLIENT_INT_PEND_ST_NORMAL HWORD_CLR_BIT(0x0001) 51 50 #define PCIE_CLIENT_SIDE_BAND_STATUS (PCIE_CLIENT_BASE + 0x20) 52 51 #define PCIE_CLIENT_PHY_ST BIT(12) 53 52 #define PCIE_CLIENT_DEBUG_OUT_0 (PCIE_CLIENT_BASE + 0x3c)
+2 -1
drivers/phy/rockchip/phy-rockchip-emmc.c
··· 8 8 9 9 #include <linux/clk.h> 10 10 #include <linux/delay.h> 11 + #include <linux/hw_bitfield.h> 11 12 #include <linux/mfd/syscon.h> 12 13 #include <linux/module.h> 13 14 #include <linux/of.h> ··· 22 21 * only if BIT(x + 16) set to 1 the BIT(x) can be written. 23 22 */ 24 23 #define HIWORD_UPDATE(val, mask, shift) \ 25 - ((val) << (shift) | (mask) << ((shift) + 16)) 24 + (FIELD_PREP_WM16((mask) << (shift), (val))) 26 25 27 26 /* Register definition */ 28 27 #define GRF_EMMCPHY_CON0 0x0
+20 -50
drivers/phy/rockchip/phy-rockchip-pcie.c
··· 8 8 9 9 #include <linux/clk.h> 10 10 #include <linux/delay.h> 11 + #include <linux/hw_bitfield.h> 11 12 #include <linux/io.h> 12 13 #include <linux/mfd/syscon.h> 13 14 #include <linux/module.h> ··· 19 18 #include <linux/regmap.h> 20 19 #include <linux/reset.h> 21 20 22 - /* 23 - * The higher 16-bit of this register is used for write protection 24 - * only if BIT(x + 16) set to 1 the BIT(x) can be written. 25 - */ 26 - #define HIWORD_UPDATE(val, mask, shift) \ 27 - ((val) << (shift) | (mask) << ((shift) + 16)) 28 21 29 22 #define PHY_MAX_LANE_NUM 4 30 - #define PHY_CFG_DATA_SHIFT 7 31 - #define PHY_CFG_ADDR_SHIFT 1 32 - #define PHY_CFG_DATA_MASK 0xf 33 - #define PHY_CFG_ADDR_MASK 0x3f 23 + #define PHY_CFG_DATA_MASK GENMASK(10, 7) 24 + #define PHY_CFG_ADDR_MASK GENMASK(6, 1) 34 25 #define PHY_CFG_WR_ENABLE 1 35 26 #define PHY_CFG_WR_DISABLE 0 36 - #define PHY_CFG_WR_SHIFT 0 37 - #define PHY_CFG_WR_MASK 1 27 + #define PHY_CFG_WR_MASK BIT(0) 38 28 #define PHY_CFG_PLL_LOCK 0x10 39 29 #define PHY_CFG_CLK_TEST 0x10 40 30 #define PHY_CFG_CLK_SCC 0x12 ··· 40 48 #define PHY_LANE_RX_DET_SHIFT 11 41 49 #define PHY_LANE_RX_DET_TH 0x1 42 50 #define PHY_LANE_IDLE_OFF 0x1 43 - #define PHY_LANE_IDLE_MASK 0x1 44 - #define PHY_LANE_IDLE_A_SHIFT 3 45 - #define PHY_LANE_IDLE_B_SHIFT 4 46 - #define PHY_LANE_IDLE_C_SHIFT 5 47 - #define PHY_LANE_IDLE_D_SHIFT 6 51 + #define PHY_LANE_IDLE_MASK BIT(3) 48 52 49 53 struct rockchip_pcie_data { 50 54 unsigned int pcie_conf; ··· 87 99 u32 addr, u32 data) 88 100 { 89 101 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, 90 - HIWORD_UPDATE(data, 91 - PHY_CFG_DATA_MASK, 92 - PHY_CFG_DATA_SHIFT) | 93 - HIWORD_UPDATE(addr, 94 - PHY_CFG_ADDR_MASK, 95 - PHY_CFG_ADDR_SHIFT)); 102 + FIELD_PREP_WM16(PHY_CFG_DATA_MASK, data) | 103 + FIELD_PREP_WM16(PHY_CFG_ADDR_MASK, addr)); 96 104 udelay(1); 97 105 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, 98 - HIWORD_UPDATE(PHY_CFG_WR_ENABLE, 99 - PHY_CFG_WR_MASK, 100 - PHY_CFG_WR_SHIFT)); 106 + FIELD_PREP_WM16(PHY_CFG_WR_MASK, PHY_CFG_WR_ENABLE)); 101 107 udelay(1); 102 108 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, 103 - HIWORD_UPDATE(PHY_CFG_WR_DISABLE, 104 - PHY_CFG_WR_MASK, 105 - PHY_CFG_WR_SHIFT)); 109 + FIELD_PREP_WM16(PHY_CFG_WR_MASK, PHY_CFG_WR_DISABLE)); 106 110 } 107 111 108 112 static int rockchip_pcie_phy_power_off(struct phy *phy) ··· 105 125 106 126 guard(mutex)(&rk_phy->pcie_mutex); 107 127 108 - regmap_write(rk_phy->reg_base, 109 - rk_phy->phy_data->pcie_laneoff, 110 - HIWORD_UPDATE(PHY_LANE_IDLE_OFF, 111 - PHY_LANE_IDLE_MASK, 112 - PHY_LANE_IDLE_A_SHIFT + inst->index)); 128 + regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_laneoff, 129 + FIELD_PREP_WM16(PHY_LANE_IDLE_MASK, 130 + PHY_LANE_IDLE_OFF) << inst->index); 113 131 114 132 if (--rk_phy->pwr_cnt) { 115 133 return 0; ··· 117 139 if (err) { 118 140 dev_err(&phy->dev, "assert phy_rst err %d\n", err); 119 141 rk_phy->pwr_cnt++; 120 - regmap_write(rk_phy->reg_base, 121 - rk_phy->phy_data->pcie_laneoff, 122 - HIWORD_UPDATE(!PHY_LANE_IDLE_OFF, 123 - PHY_LANE_IDLE_MASK, 124 - PHY_LANE_IDLE_A_SHIFT + inst->index)); 142 + regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_laneoff, 143 + FIELD_PREP_WM16(PHY_LANE_IDLE_MASK, 144 + !PHY_LANE_IDLE_OFF) << inst->index); 125 145 return err; 126 146 } 127 147 ··· 135 159 136 160 guard(mutex)(&rk_phy->pcie_mutex); 137 161 138 - regmap_write(rk_phy->reg_base, 139 - rk_phy->phy_data->pcie_laneoff, 140 - HIWORD_UPDATE(!PHY_LANE_IDLE_OFF, 141 - PHY_LANE_IDLE_MASK, 142 - PHY_LANE_IDLE_A_SHIFT + inst->index)); 162 + regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_laneoff, 163 + FIELD_PREP_WM16(PHY_LANE_IDLE_MASK, 164 + !PHY_LANE_IDLE_OFF) << inst->index); 143 165 144 166 if (rk_phy->pwr_cnt++) { 145 167 return 0; ··· 151 177 } 152 178 153 179 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, 154 - HIWORD_UPDATE(PHY_CFG_PLL_LOCK, 155 - PHY_CFG_ADDR_MASK, 156 - PHY_CFG_ADDR_SHIFT)); 180 + FIELD_PREP_WM16(PHY_CFG_ADDR_MASK, PHY_CFG_PLL_LOCK)); 157 181 158 182 /* 159 183 * No documented timeout value for phy operation below, ··· 182 210 } 183 211 184 212 regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, 185 - HIWORD_UPDATE(PHY_CFG_PLL_LOCK, 186 - PHY_CFG_ADDR_MASK, 187 - PHY_CFG_ADDR_SHIFT)); 213 + FIELD_PREP_WM16(PHY_CFG_ADDR_MASK, PHY_CFG_PLL_LOCK)); 188 214 189 215 err = regmap_read_poll_timeout(rk_phy->reg_base, 190 216 rk_phy->phy_data->pcie_status,
+3 -8
drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
··· 8 8 #include <dt-bindings/phy/phy.h> 9 9 #include <linux/bitfield.h> 10 10 #include <linux/clk.h> 11 + #include <linux/hw_bitfield.h> 11 12 #include <linux/init.h> 12 13 #include <linux/kernel.h> 13 14 #include <linux/mfd/syscon.h> ··· 20 19 #include <linux/pm_runtime.h> 21 20 #include <linux/regmap.h> 22 21 #include <linux/reset.h> 23 - 24 - #define FIELD_PREP_HIWORD(_mask, _val) \ 25 - ( \ 26 - FIELD_PREP((_mask), (_val)) | \ 27 - ((_mask) << 16) \ 28 - ) 29 22 30 23 #define BIAS_CON0 0x0000 31 24 #define I_RES_CNTL_MASK GENMASK(6, 4) ··· 247 252 248 253 /* MIPI_CDPHY_GRF registers */ 249 254 #define MIPI_DCPHY_GRF_CON0 0x0000 250 - #define S_CPHY_MODE FIELD_PREP_HIWORD(BIT(3), 1) 251 - #define M_CPHY_MODE FIELD_PREP_HIWORD(BIT(0), 1) 255 + #define S_CPHY_MODE FIELD_PREP_WM16(BIT(3), 1) 256 + #define M_CPHY_MODE FIELD_PREP_WM16(BIT(0), 1) 252 257 253 258 enum hs_drv_res_ohm { 254 259 STRENGTH_30_OHM = 0x8,
+20 -31
drivers/phy/rockchip/phy-rockchip-usb.c
··· 8 8 9 9 #include <linux/clk.h> 10 10 #include <linux/clk-provider.h> 11 + #include <linux/hw_bitfield.h> 11 12 #include <linux/io.h> 12 13 #include <linux/kernel.h> 13 14 #include <linux/module.h> ··· 25 24 26 25 static int enable_usb_uart; 27 26 28 - #define HIWORD_UPDATE(val, mask) \ 29 - ((val) | (mask) << 16) 30 - 31 27 #define UOC_CON0 0x00 32 28 #define UOC_CON0_SIDDQ BIT(13) 33 29 #define UOC_CON0_DISABLE BIT(4) ··· 36 38 #define UOC_CON3 0x0c 37 39 /* bits present on rk3188 and rk3288 phys */ 38 40 #define UOC_CON3_UTMI_TERMSEL_FULLSPEED BIT(5) 39 - #define UOC_CON3_UTMI_XCVRSEELCT_FSTRANSC (1 << 3) 40 - #define UOC_CON3_UTMI_XCVRSEELCT_MASK (3 << 3) 41 - #define UOC_CON3_UTMI_OPMODE_NODRIVING (1 << 1) 42 - #define UOC_CON3_UTMI_OPMODE_MASK (3 << 1) 41 + #define UOC_CON3_UTMI_XCVRSEELCT_FSTRANSC 1UL 42 + #define UOC_CON3_UTMI_XCVRSEELCT_MASK GENMASK(4, 3) 43 + #define UOC_CON3_UTMI_OPMODE_NODRIVING 1UL 44 + #define UOC_CON3_UTMI_OPMODE_MASK GENMASK(2, 1) 43 45 #define UOC_CON3_UTMI_SUSPENDN BIT(0) 44 46 45 47 struct rockchip_usb_phys { ··· 77 79 static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy, 78 80 bool siddq) 79 81 { 80 - u32 val = HIWORD_UPDATE(siddq ? UOC_CON0_SIDDQ : 0, UOC_CON0_SIDDQ); 82 + u32 val = FIELD_PREP_WM16(UOC_CON0_SIDDQ, siddq); 81 83 82 84 return regmap_write(phy->base->reg_base, phy->reg_offset, val); 83 85 } ··· 330 332 * but were not present in the original code. 331 333 * Also disable the analog phy components to save power. 332 334 */ 333 - val = HIWORD_UPDATE(UOC_CON0_COMMON_ON_N 334 - | UOC_CON0_DISABLE 335 - | UOC_CON0_SIDDQ, 336 - UOC_CON0_COMMON_ON_N 337 - | UOC_CON0_DISABLE 338 - | UOC_CON0_SIDDQ); 335 + val = FIELD_PREP_WM16(UOC_CON0_COMMON_ON_N, 1) | 336 + FIELD_PREP_WM16(UOC_CON0_DISABLE, 1) | 337 + FIELD_PREP_WM16(UOC_CON0_SIDDQ, 1); 339 338 ret = regmap_write(grf, regoffs + UOC_CON0, val); 340 339 if (ret) 341 340 return ret; 342 341 343 - val = HIWORD_UPDATE(UOC_CON2_SOFT_CON_SEL, 344 - UOC_CON2_SOFT_CON_SEL); 342 + val = FIELD_PREP_WM16(UOC_CON2_SOFT_CON_SEL, 1); 345 343 ret = regmap_write(grf, regoffs + UOC_CON2, val); 346 344 if (ret) 347 345 return ret; 348 346 349 - val = HIWORD_UPDATE(UOC_CON3_UTMI_OPMODE_NODRIVING 350 - | UOC_CON3_UTMI_XCVRSEELCT_FSTRANSC 351 - | UOC_CON3_UTMI_TERMSEL_FULLSPEED, 352 - UOC_CON3_UTMI_SUSPENDN 353 - | UOC_CON3_UTMI_OPMODE_MASK 354 - | UOC_CON3_UTMI_XCVRSEELCT_MASK 355 - | UOC_CON3_UTMI_TERMSEL_FULLSPEED); 347 + val = FIELD_PREP_WM16(UOC_CON3_UTMI_SUSPENDN, 0) | 348 + FIELD_PREP_WM16(UOC_CON3_UTMI_OPMODE_MASK, 349 + UOC_CON3_UTMI_OPMODE_NODRIVING) | 350 + FIELD_PREP_WM16(UOC_CON3_UTMI_XCVRSEELCT_MASK, 351 + UOC_CON3_UTMI_XCVRSEELCT_FSTRANSC) | 352 + FIELD_PREP_WM16(UOC_CON3_UTMI_TERMSEL_FULLSPEED, 1); 356 353 ret = regmap_write(grf, UOC_CON3, val); 357 354 if (ret) 358 355 return ret; ··· 373 380 if (ret) 374 381 return ret; 375 382 376 - val = HIWORD_UPDATE(RK3188_UOC0_CON0_BYPASSSEL 377 - | RK3188_UOC0_CON0_BYPASSDMEN, 378 - RK3188_UOC0_CON0_BYPASSSEL 379 - | RK3188_UOC0_CON0_BYPASSDMEN); 383 + val = FIELD_PREP_WM16(RK3188_UOC0_CON0_BYPASSSEL, 1) | 384 + FIELD_PREP_WM16(RK3188_UOC0_CON0_BYPASSDMEN, 1); 380 385 ret = regmap_write(grf, RK3188_UOC0_CON0, val); 381 386 if (ret) 382 387 return ret; ··· 421 430 if (ret) 422 431 return ret; 423 432 424 - val = HIWORD_UPDATE(RK3288_UOC0_CON3_BYPASSSEL 425 - | RK3288_UOC0_CON3_BYPASSDMEN, 426 - RK3288_UOC0_CON3_BYPASSSEL 427 - | RK3288_UOC0_CON3_BYPASSDMEN); 433 + val = FIELD_PREP_WM16(RK3288_UOC0_CON3_BYPASSSEL, 1) | 434 + FIELD_PREP_WM16(RK3288_UOC0_CON3_BYPASSDMEN, 1); 428 435 ret = regmap_write(grf, RK3288_UOC0_CON3, val); 429 436 if (ret) 430 437 return ret;
+17 -18
drivers/soc/rockchip/grf.c
··· 6 6 */ 7 7 8 8 #include <linux/err.h> 9 + #include <linux/hw_bitfield.h> 9 10 #include <linux/mfd/syscon.h> 10 11 #include <linux/of.h> 11 12 #include <linux/platform_device.h> 12 13 #include <linux/regmap.h> 13 14 14 - #define HIWORD_UPDATE(val, mask, shift) \ 15 - ((val) << (shift) | (mask) << ((shift) + 16)) 16 15 17 16 struct rockchip_grf_value { 18 17 const char *desc; ··· 31 32 * Disable auto jtag/sdmmc switching that causes issues with the 32 33 * clock-framework and the mmc controllers making them unreliable. 33 34 */ 34 - { "jtag switching", RK3036_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 11) }, 35 + { "jtag switching", RK3036_GRF_SOC_CON0, FIELD_PREP_WM16_CONST(BIT(11), 0) }, 35 36 }; 36 37 37 38 static const struct rockchip_grf_info rk3036_grf __initconst = { ··· 43 44 #define RK3128_GRF_SOC_CON1 0x144 44 45 45 46 static const struct rockchip_grf_value rk3128_defaults[] __initconst = { 46 - { "jtag switching", RK3128_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 8) }, 47 - { "vpu main clock", RK3128_GRF_SOC_CON1, HIWORD_UPDATE(0, 1, 10) }, 47 + { "jtag switching", RK3128_GRF_SOC_CON0, FIELD_PREP_WM16_CONST(BIT(8), 0) }, 48 + { "vpu main clock", RK3128_GRF_SOC_CON1, FIELD_PREP_WM16_CONST(BIT(10), 0) }, 48 49 }; 49 50 50 51 static const struct rockchip_grf_info rk3128_grf __initconst = { ··· 55 56 #define RK3228_GRF_SOC_CON6 0x418 56 57 57 58 static const struct rockchip_grf_value rk3228_defaults[] __initconst = { 58 - { "jtag switching", RK3228_GRF_SOC_CON6, HIWORD_UPDATE(0, 1, 8) }, 59 + { "jtag switching", RK3228_GRF_SOC_CON6, FIELD_PREP_WM16_CONST(BIT(8), 0) }, 59 60 }; 60 61 61 62 static const struct rockchip_grf_info rk3228_grf __initconst = { ··· 67 68 #define RK3288_GRF_SOC_CON2 0x24c 68 69 69 70 static const struct rockchip_grf_value rk3288_defaults[] __initconst = { 70 - { "jtag switching", RK3288_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 12) }, 71 - { "pwm select", RK3288_GRF_SOC_CON2, HIWORD_UPDATE(1, 1, 0) }, 71 + { "jtag switching", RK3288_GRF_SOC_CON0, FIELD_PREP_WM16_CONST(BIT(12), 0) }, 72 + { "pwm select", RK3288_GRF_SOC_CON2, FIELD_PREP_WM16_CONST(BIT(0), 1) }, 72 73 }; 73 74 74 75 static const struct rockchip_grf_info rk3288_grf __initconst = { ··· 79 80 #define RK3328_GRF_SOC_CON4 0x410 80 81 81 82 static const struct rockchip_grf_value rk3328_defaults[] __initconst = { 82 - { "jtag switching", RK3328_GRF_SOC_CON4, HIWORD_UPDATE(0, 1, 12) }, 83 + { "jtag switching", RK3328_GRF_SOC_CON4, FIELD_PREP_WM16_CONST(BIT(12), 0) }, 83 84 }; 84 85 85 86 static const struct rockchip_grf_info rk3328_grf __initconst = { ··· 90 91 #define RK3368_GRF_SOC_CON15 0x43c 91 92 92 93 static const struct rockchip_grf_value rk3368_defaults[] __initconst = { 93 - { "jtag switching", RK3368_GRF_SOC_CON15, HIWORD_UPDATE(0, 1, 13) }, 94 + { "jtag switching", RK3368_GRF_SOC_CON15, FIELD_PREP_WM16_CONST(BIT(13), 0) }, 94 95 }; 95 96 96 97 static const struct rockchip_grf_info rk3368_grf __initconst = { ··· 101 102 #define RK3399_GRF_SOC_CON7 0xe21c 102 103 103 104 static const struct rockchip_grf_value rk3399_defaults[] __initconst = { 104 - { "jtag switching", RK3399_GRF_SOC_CON7, HIWORD_UPDATE(0, 1, 12) }, 105 + { "jtag switching", RK3399_GRF_SOC_CON7, FIELD_PREP_WM16_CONST(BIT(12), 0) }, 105 106 }; 106 107 107 108 static const struct rockchip_grf_info rk3399_grf __initconst = { ··· 112 113 #define RK3566_GRF_USB3OTG0_CON1 0x0104 113 114 114 115 static const struct rockchip_grf_value rk3566_defaults[] __initconst = { 115 - { "usb3otg port switch", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(0, 1, 12) }, 116 - { "usb3otg clock switch", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(1, 1, 7) }, 117 - { "usb3otg disable usb3", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(1, 1, 0) }, 116 + { "usb3otg port switch", RK3566_GRF_USB3OTG0_CON1, FIELD_PREP_WM16_CONST(BIT(12), 0) }, 117 + { "usb3otg clock switch", RK3566_GRF_USB3OTG0_CON1, FIELD_PREP_WM16_CONST(BIT(7), 1) }, 118 + { "usb3otg disable usb3", RK3566_GRF_USB3OTG0_CON1, FIELD_PREP_WM16_CONST(BIT(0), 1) }, 118 119 }; 119 120 120 121 static const struct rockchip_grf_info rk3566_pipegrf __initconst = { ··· 125 126 #define RK3576_SYSGRF_SOC_CON1 0x0004 126 127 127 128 static const struct rockchip_grf_value rk3576_defaults_sys_grf[] __initconst = { 128 - { "i3c0 weakpull", RK3576_SYSGRF_SOC_CON1, HIWORD_UPDATE(3, 3, 6) }, 129 - { "i3c1 weakpull", RK3576_SYSGRF_SOC_CON1, HIWORD_UPDATE(3, 3, 8) }, 129 + { "i3c0 weakpull", RK3576_SYSGRF_SOC_CON1, FIELD_PREP_WM16_CONST(GENMASK(7, 6), 3) }, 130 + { "i3c1 weakpull", RK3576_SYSGRF_SOC_CON1, FIELD_PREP_WM16_CONST(GENMASK(9, 8), 3) }, 130 131 }; 131 132 132 133 static const struct rockchip_grf_info rk3576_sysgrf __initconst = { ··· 137 138 #define RK3576_IOCGRF_MISC_CON 0x04F0 138 139 139 140 static const struct rockchip_grf_value rk3576_defaults_ioc_grf[] __initconst = { 140 - { "jtag switching", RK3576_IOCGRF_MISC_CON, HIWORD_UPDATE(0, 1, 1) }, 141 + { "jtag switching", RK3576_IOCGRF_MISC_CON, FIELD_PREP_WM16_CONST(BIT(1), 0) }, 141 142 }; 142 143 143 144 static const struct rockchip_grf_info rk3576_iocgrf __initconst = { ··· 148 149 #define RK3588_GRF_SOC_CON6 0x0318 149 150 150 151 static const struct rockchip_grf_value rk3588_defaults[] __initconst = { 151 - { "jtag switching", RK3588_GRF_SOC_CON6, HIWORD_UPDATE(0, 1, 14) }, 152 + { "jtag switching", RK3588_GRF_SOC_CON6, FIELD_PREP_WM16_CONST(BIT(14), 0) }, 152 153 }; 153 154 154 155 static const struct rockchip_grf_info rk3588_sysgrf __initconst = {
+62
include/linux/hw_bitfield.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * Copyright (C) 2025, Collabora Ltd. 4 + */ 5 + 6 + #ifndef _LINUX_HW_BITFIELD_H 7 + #define _LINUX_HW_BITFIELD_H 8 + 9 + #include <linux/bitfield.h> 10 + #include <linux/build_bug.h> 11 + #include <linux/limits.h> 12 + 13 + /** 14 + * FIELD_PREP_WM16() - prepare a bitfield element with a mask in the upper half 15 + * @_mask: shifted mask defining the field's length and position 16 + * @_val: value to put in the field 17 + * 18 + * FIELD_PREP_WM16() masks and shifts up the value, as well as bitwise ORs the 19 + * result with the mask shifted up by 16. 20 + * 21 + * This is useful for a common design of hardware registers where the upper 22 + * 16-bit half of a 32-bit register is used as a write-enable mask. In such a 23 + * register, a bit in the lower half is only updated if the corresponding bit 24 + * in the upper half is high. 25 + */ 26 + #define FIELD_PREP_WM16(_mask, _val) \ 27 + ({ \ 28 + typeof(_val) __val = _val; \ 29 + typeof(_mask) __mask = _mask; \ 30 + __BF_FIELD_CHECK(__mask, ((u16)0U), __val, \ 31 + "HWORD_UPDATE: "); \ 32 + (((typeof(__mask))(__val) << __bf_shf(__mask)) & (__mask)) | \ 33 + ((__mask) << 16); \ 34 + }) 35 + 36 + /** 37 + * FIELD_PREP_WM16_CONST() - prepare a constant bitfield element with a mask in 38 + * the upper half 39 + * @_mask: shifted mask defining the field's length and position 40 + * @_val: value to put in the field 41 + * 42 + * FIELD_PREP_WM16_CONST() masks and shifts up the value, as well as bitwise ORs 43 + * the result with the mask shifted up by 16. 44 + * 45 + * This is useful for a common design of hardware registers where the upper 46 + * 16-bit half of a 32-bit register is used as a write-enable mask. In such a 47 + * register, a bit in the lower half is only updated if the corresponding bit 48 + * in the upper half is high. 49 + * 50 + * Unlike FIELD_PREP_WM16(), this is a constant expression and can therefore 51 + * be used in initializers. Error checking is less comfortable for this 52 + * version. 53 + */ 54 + #define FIELD_PREP_WM16_CONST(_mask, _val) \ 55 + ( \ 56 + FIELD_PREP_CONST(_mask, _val) | \ 57 + (BUILD_BUG_ON_ZERO(const_true((u64)(_mask) > U16_MAX)) + \ 58 + ((_mask) << 16)) \ 59 + ) 60 + 61 + 62 + #endif /* _LINUX_HW_BITFIELD_H */
+13
lib/Kconfig.debug
··· 2621 2621 2622 2622 If unsure, say N. 2623 2623 2624 + config FIND_BIT_BENCHMARK_RUST 2625 + tristate "Test find_bit functions in Rust" 2626 + depends on RUST 2627 + help 2628 + This builds the "find_bit_benchmark_rust" module. It is a micro 2629 + benchmark that measures the performance of Rust functions that 2630 + correspond to the find_*_bit() operations in C. It follows the 2631 + FIND_BIT_BENCHMARK closely but will in general not yield same 2632 + numbers due to extra bounds checks and overhead of foreign 2633 + function calls. 2634 + 2635 + If unsure, say N. 2636 + 2624 2637 config TEST_FIRMWARE 2625 2638 tristate "Test firmware loading via userspace interface" 2626 2639 depends on FW_LOADER
+1
lib/Makefile
··· 62 62 obj-$(CONFIG_TEST_HEXDUMP) += test_hexdump.o 63 63 obj-y += kstrtox.o 64 64 obj-$(CONFIG_FIND_BIT_BENCHMARK) += find_bit_benchmark.o 65 + obj-$(CONFIG_FIND_BIT_BENCHMARK_RUST) += find_bit_benchmark_rust.o 65 66 obj-$(CONFIG_TEST_BPF) += test_bpf.o 66 67 test_dhry-objs := dhry_1.o dhry_2.o dhry_run.o 67 68 obj-$(CONFIG_TEST_DHRY) += test_dhry.o
+104
lib/find_bit_benchmark_rust.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + //! Benchmark for find_bit-like methods in Bitmap Rust API. 3 + 4 + use kernel::alloc::flags::GFP_KERNEL; 5 + use kernel::bindings; 6 + use kernel::bitmap::BitmapVec; 7 + use kernel::error::{code, Result}; 8 + use kernel::prelude::module; 9 + use kernel::time::{Instant, Monotonic}; 10 + use kernel::ThisModule; 11 + use kernel::{pr_cont, pr_err}; 12 + 13 + const BITMAP_LEN: usize = 4096 * 8 * 10; 14 + // Reciprocal of the fraction of bits that are set in sparse bitmap. 15 + const SPARSENESS: usize = 500; 16 + 17 + /// Test module that benchmarks performance of traversing bitmaps. 18 + struct Benchmark(); 19 + 20 + fn test_next_bit(bitmap: &BitmapVec) { 21 + let time = Instant::<Monotonic>::now(); 22 + let mut cnt = 0; 23 + let mut i = 0; 24 + 25 + while let Some(index) = bitmap.next_bit(i) { 26 + cnt += 1; 27 + i = index + 1; 28 + // CONFIG_RUST_BITMAP_HARDENED enforces strict bounds. 29 + if i == BITMAP_LEN { 30 + break; 31 + } 32 + } 33 + 34 + let delta = time.elapsed(); 35 + pr_cont!( 36 + "\nnext_bit: {:18} ns, {:6} iterations", 37 + delta.as_nanos(), 38 + cnt 39 + ); 40 + } 41 + 42 + fn test_next_zero_bit(bitmap: &BitmapVec) { 43 + let time = Instant::<Monotonic>::now(); 44 + let mut cnt = 0; 45 + let mut i = 0; 46 + 47 + while let Some(index) = bitmap.next_zero_bit(i) { 48 + cnt += 1; 49 + i = index + 1; 50 + // CONFIG_RUST_BITMAP_HARDENED enforces strict bounds. 51 + if i == BITMAP_LEN { 52 + break; 53 + } 54 + } 55 + 56 + let delta = time.elapsed(); 57 + pr_cont!( 58 + "\nnext_zero_bit: {:18} ns, {:6} iterations", 59 + delta.as_nanos(), 60 + cnt 61 + ); 62 + } 63 + 64 + fn find_bit_test() { 65 + pr_err!("Benchmark"); 66 + pr_cont!("\nStart testing find_bit() Rust with random-filled bitmap"); 67 + 68 + let mut bitmap = BitmapVec::new(BITMAP_LEN, GFP_KERNEL).expect("alloc bitmap failed"); 69 + bitmap.fill_random(); 70 + 71 + test_next_bit(&bitmap); 72 + test_next_zero_bit(&bitmap); 73 + 74 + pr_cont!("\nStart testing find_bit() Rust with sparse bitmap"); 75 + 76 + let mut bitmap = BitmapVec::new(BITMAP_LEN, GFP_KERNEL).expect("alloc sparse bitmap failed"); 77 + let nbits = BITMAP_LEN / SPARSENESS; 78 + for _i in 0..nbits { 79 + // SAFETY: __get_random_u32_below is safe to call with any u32 argument. 80 + let bit = 81 + unsafe { bindings::__get_random_u32_below(BITMAP_LEN.try_into().unwrap()) as usize }; 82 + bitmap.set_bit(bit); 83 + } 84 + 85 + test_next_bit(&bitmap); 86 + test_next_zero_bit(&bitmap); 87 + pr_cont!("\n"); 88 + } 89 + 90 + impl kernel::Module for Benchmark { 91 + fn init(_module: &'static ThisModule) -> Result<Self> { 92 + find_bit_test(); 93 + // Return error so test module can be inserted again without rmmod. 94 + Err(code::EINVAL) 95 + } 96 + } 97 + 98 + module! { 99 + type: Benchmark, 100 + name: "find_bit_benchmark_rust", 101 + authors: ["Burak Emir <bqe@google.com>"], 102 + description: "Module with benchmark for bitmap Rust API", 103 + license: "GPL v2", 104 + }
+2
rust/bindings/bindings_helper.h
··· 36 36 #include <drm/drm_ioctl.h> 37 37 #include <kunit/test.h> 38 38 #include <linux/auxiliary_bus.h> 39 + #include <linux/bitmap.h> 39 40 #include <linux/blk-mq.h> 40 41 #include <linux/blk_types.h> 41 42 #include <linux/blkdev.h> ··· 69 68 #include <linux/pm_opp.h> 70 69 #include <linux/poll.h> 71 70 #include <linux/property.h> 71 + #include <linux/random.h> 72 72 #include <linux/refcount.h> 73 73 #include <linux/regulator/consumer.h> 74 74 #include <linux/sched.h>
+9
rust/helpers/bitmap.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/bitmap.h> 4 + 5 + void rust_helper_bitmap_copy_and_extend(unsigned long *to, const unsigned long *from, 6 + unsigned int count, unsigned int size) 7 + { 8 + bitmap_copy_and_extend(to, from, count, size); 9 + }
+23
rust/helpers/bitops.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/bitops.h> 4 + 5 + void rust_helper___set_bit(unsigned long nr, unsigned long *addr) 6 + { 7 + __set_bit(nr, addr); 8 + } 9 + 10 + void rust_helper___clear_bit(unsigned long nr, unsigned long *addr) 11 + { 12 + __clear_bit(nr, addr); 13 + } 14 + 15 + void rust_helper_set_bit(unsigned long nr, volatile unsigned long *addr) 16 + { 17 + set_bit(nr, addr); 18 + } 19 + 20 + void rust_helper_clear_bit(unsigned long nr, volatile unsigned long *addr) 21 + { 22 + clear_bit(nr, addr); 23 + }
+2
rust/helpers/helpers.c
··· 10 10 #include "atomic.c" 11 11 #include "auxiliary.c" 12 12 #include "barrier.c" 13 + #include "bitmap.c" 14 + #include "bitops.c" 13 15 #include "blk.c" 14 16 #include "bug.c" 15 17 #include "build_assert.c"
+600
rust/kernel/bitmap.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + // Copyright (C) 2025 Google LLC. 4 + 5 + //! Rust API for bitmap. 6 + //! 7 + //! C headers: [`include/linux/bitmap.h`](srctree/include/linux/bitmap.h). 8 + 9 + use crate::alloc::{AllocError, Flags}; 10 + use crate::bindings; 11 + #[cfg(not(CONFIG_RUST_BITMAP_HARDENED))] 12 + use crate::pr_err; 13 + use core::ptr::NonNull; 14 + 15 + const BITS_PER_LONG: usize = bindings::BITS_PER_LONG as usize; 16 + 17 + /// Represents a C bitmap. Wraps underlying C bitmap API. 18 + /// 19 + /// # Invariants 20 + /// 21 + /// Must reference a `[c_ulong]` long enough to fit `data.len()` bits. 22 + #[cfg_attr(CONFIG_64BIT, repr(align(8)))] 23 + #[cfg_attr(not(CONFIG_64BIT), repr(align(4)))] 24 + pub struct Bitmap { 25 + data: [()], 26 + } 27 + 28 + impl Bitmap { 29 + /// Borrows a C bitmap. 30 + /// 31 + /// # Safety 32 + /// 33 + /// * `ptr` holds a non-null address of an initialized array of `unsigned long` 34 + /// that is large enough to hold `nbits` bits. 35 + /// * the array must not be freed for the lifetime of this [`Bitmap`] 36 + /// * concurrent access only happens through atomic operations 37 + pub unsafe fn from_raw<'a>(ptr: *const usize, nbits: usize) -> &'a Bitmap { 38 + let data: *const [()] = core::ptr::slice_from_raw_parts(ptr.cast(), nbits); 39 + // INVARIANT: `data` references an initialized array that can hold `nbits` bits. 40 + // SAFETY: 41 + // The caller guarantees that `data` (derived from `ptr` and `nbits`) 42 + // points to a valid, initialized, and appropriately sized memory region 43 + // that will not be freed for the lifetime 'a. 44 + // We are casting `*const [()]` to `*const Bitmap`. The `Bitmap` 45 + // struct is a ZST with a `data: [()]` field. This means its layout 46 + // is compatible with a slice of `()`, and effectively it's a "thin pointer" 47 + // (its size is 0 and alignment is 1). The `slice_from_raw_parts` 48 + // function correctly encodes the length (number of bits, not elements) 49 + // into the metadata of the fat pointer. Therefore, dereferencing this 50 + // pointer as `&Bitmap` is safe given the caller's guarantees. 51 + unsafe { &*(data as *const Bitmap) } 52 + } 53 + 54 + /// Borrows a C bitmap exclusively. 55 + /// 56 + /// # Safety 57 + /// 58 + /// * `ptr` holds a non-null address of an initialized array of `unsigned long` 59 + /// that is large enough to hold `nbits` bits. 60 + /// * the array must not be freed for the lifetime of this [`Bitmap`] 61 + /// * no concurrent access may happen. 62 + pub unsafe fn from_raw_mut<'a>(ptr: *mut usize, nbits: usize) -> &'a mut Bitmap { 63 + let data: *mut [()] = core::ptr::slice_from_raw_parts_mut(ptr.cast(), nbits); 64 + // INVARIANT: `data` references an initialized array that can hold `nbits` bits. 65 + // SAFETY: 66 + // The caller guarantees that `data` (derived from `ptr` and `nbits`) 67 + // points to a valid, initialized, and appropriately sized memory region 68 + // that will not be freed for the lifetime 'a. 69 + // Furthermore, the caller guarantees no concurrent access will happen, 70 + // which upholds the exclusivity requirement for a mutable reference. 71 + // Similar to `from_raw`, casting `*mut [()]` to `*mut Bitmap` is 72 + // safe because `Bitmap` is a ZST with a `data: [()]` field, 73 + // making its layout compatible with a slice of `()`. 74 + unsafe { &mut *(data as *mut Bitmap) } 75 + } 76 + 77 + /// Returns a raw pointer to the backing [`Bitmap`]. 78 + pub fn as_ptr(&self) -> *const usize { 79 + core::ptr::from_ref::<Bitmap>(self).cast::<usize>() 80 + } 81 + 82 + /// Returns a mutable raw pointer to the backing [`Bitmap`]. 83 + pub fn as_mut_ptr(&mut self) -> *mut usize { 84 + core::ptr::from_mut::<Bitmap>(self).cast::<usize>() 85 + } 86 + 87 + /// Returns length of this [`Bitmap`]. 88 + #[expect(clippy::len_without_is_empty)] 89 + pub fn len(&self) -> usize { 90 + self.data.len() 91 + } 92 + } 93 + 94 + /// Holds either a pointer to array of `unsigned long` or a small bitmap. 95 + #[repr(C)] 96 + union BitmapRepr { 97 + bitmap: usize, 98 + ptr: NonNull<usize>, 99 + } 100 + 101 + macro_rules! bitmap_assert { 102 + ($cond:expr, $($arg:tt)+) => { 103 + #[cfg(CONFIG_RUST_BITMAP_HARDENED)] 104 + assert!($cond, $($arg)*); 105 + } 106 + } 107 + 108 + macro_rules! bitmap_assert_return { 109 + ($cond:expr, $($arg:tt)+) => { 110 + #[cfg(CONFIG_RUST_BITMAP_HARDENED)] 111 + assert!($cond, $($arg)*); 112 + 113 + #[cfg(not(CONFIG_RUST_BITMAP_HARDENED))] 114 + if !($cond) { 115 + pr_err!($($arg)*); 116 + return 117 + } 118 + } 119 + } 120 + 121 + /// Represents an owned bitmap. 122 + /// 123 + /// Wraps underlying C bitmap API. See [`Bitmap`] for available 124 + /// methods. 125 + /// 126 + /// # Examples 127 + /// 128 + /// Basic usage 129 + /// 130 + /// ``` 131 + /// use kernel::alloc::flags::GFP_KERNEL; 132 + /// use kernel::bitmap::BitmapVec; 133 + /// 134 + /// let mut b = BitmapVec::new(16, GFP_KERNEL)?; 135 + /// 136 + /// assert_eq!(16, b.len()); 137 + /// for i in 0..16 { 138 + /// if i % 4 == 0 { 139 + /// b.set_bit(i); 140 + /// } 141 + /// } 142 + /// assert_eq!(Some(0), b.next_bit(0)); 143 + /// assert_eq!(Some(1), b.next_zero_bit(0)); 144 + /// assert_eq!(Some(4), b.next_bit(1)); 145 + /// assert_eq!(Some(5), b.next_zero_bit(4)); 146 + /// assert_eq!(Some(12), b.last_bit()); 147 + /// # Ok::<(), Error>(()) 148 + /// ``` 149 + /// 150 + /// # Invariants 151 + /// 152 + /// * `nbits` is `<= i32::MAX` and never changes. 153 + /// * if `nbits <= bindings::BITS_PER_LONG`, then `repr` is a `usize`. 154 + /// * otherwise, `repr` holds a non-null pointer to an initialized 155 + /// array of `unsigned long` that is large enough to hold `nbits` bits. 156 + pub struct BitmapVec { 157 + /// Representation of bitmap. 158 + repr: BitmapRepr, 159 + /// Length of this bitmap. Must be `<= i32::MAX`. 160 + nbits: usize, 161 + } 162 + 163 + impl core::ops::Deref for BitmapVec { 164 + type Target = Bitmap; 165 + 166 + fn deref(&self) -> &Bitmap { 167 + let ptr = if self.nbits <= BITS_PER_LONG { 168 + // SAFETY: Bitmap is represented inline. 169 + unsafe { core::ptr::addr_of!(self.repr.bitmap) } 170 + } else { 171 + // SAFETY: Bitmap is represented as array of `unsigned long`. 172 + unsafe { self.repr.ptr.as_ptr() } 173 + }; 174 + 175 + // SAFETY: We got the right pointer and invariants of [`Bitmap`] hold. 176 + // An inline bitmap is treated like an array with single element. 177 + unsafe { Bitmap::from_raw(ptr, self.nbits) } 178 + } 179 + } 180 + 181 + impl core::ops::DerefMut for BitmapVec { 182 + fn deref_mut(&mut self) -> &mut Bitmap { 183 + let ptr = if self.nbits <= BITS_PER_LONG { 184 + // SAFETY: Bitmap is represented inline. 185 + unsafe { core::ptr::addr_of_mut!(self.repr.bitmap) } 186 + } else { 187 + // SAFETY: Bitmap is represented as array of `unsigned long`. 188 + unsafe { self.repr.ptr.as_ptr() } 189 + }; 190 + 191 + // SAFETY: We got the right pointer and invariants of [`BitmapVec`] hold. 192 + // An inline bitmap is treated like an array with single element. 193 + unsafe { Bitmap::from_raw_mut(ptr, self.nbits) } 194 + } 195 + } 196 + 197 + /// Enable ownership transfer to other threads. 198 + /// 199 + /// SAFETY: We own the underlying bitmap representation. 200 + unsafe impl Send for BitmapVec {} 201 + 202 + /// Enable unsynchronized concurrent access to [`BitmapVec`] through shared references. 203 + /// 204 + /// SAFETY: `deref()` will return a reference to a [`Bitmap`]. Its methods 205 + /// take immutable references are either atomic or read-only. 206 + unsafe impl Sync for BitmapVec {} 207 + 208 + impl Drop for BitmapVec { 209 + fn drop(&mut self) { 210 + if self.nbits <= BITS_PER_LONG { 211 + return; 212 + } 213 + // SAFETY: `self.ptr` was returned by the C `bitmap_zalloc`. 214 + // 215 + // INVARIANT: there is no other use of the `self.ptr` after this 216 + // call and the value is being dropped so the broken invariant is 217 + // not observable on function exit. 218 + unsafe { bindings::bitmap_free(self.repr.ptr.as_ptr()) }; 219 + } 220 + } 221 + 222 + impl BitmapVec { 223 + /// Constructs a new [`BitmapVec`]. 224 + /// 225 + /// Fails with [`AllocError`] when the [`BitmapVec`] could not be allocated. This 226 + /// includes the case when `nbits` is greater than `i32::MAX`. 227 + #[inline] 228 + pub fn new(nbits: usize, flags: Flags) -> Result<Self, AllocError> { 229 + if nbits <= BITS_PER_LONG { 230 + return Ok(BitmapVec { 231 + repr: BitmapRepr { bitmap: 0 }, 232 + nbits, 233 + }); 234 + } 235 + if nbits > i32::MAX.try_into().unwrap() { 236 + return Err(AllocError); 237 + } 238 + let nbits_u32 = u32::try_from(nbits).unwrap(); 239 + // SAFETY: `BITS_PER_LONG < nbits` and `nbits <= i32::MAX`. 240 + let ptr = unsafe { bindings::bitmap_zalloc(nbits_u32, flags.as_raw()) }; 241 + let ptr = NonNull::new(ptr).ok_or(AllocError)?; 242 + // INVARIANT: `ptr` returned by C `bitmap_zalloc` and `nbits` checked. 243 + Ok(BitmapVec { 244 + repr: BitmapRepr { ptr }, 245 + nbits, 246 + }) 247 + } 248 + 249 + /// Returns length of this [`Bitmap`]. 250 + #[allow(clippy::len_without_is_empty)] 251 + #[inline] 252 + pub fn len(&self) -> usize { 253 + self.nbits 254 + } 255 + 256 + /// Fills this `Bitmap` with random bits. 257 + #[cfg(CONFIG_FIND_BIT_BENCHMARK_RUST)] 258 + pub fn fill_random(&mut self) { 259 + // SAFETY: `self.as_mut_ptr` points to either an array of the 260 + // appropriate length or one usize. 261 + unsafe { 262 + bindings::get_random_bytes( 263 + self.as_mut_ptr().cast::<ffi::c_void>(), 264 + usize::div_ceil(self.nbits, bindings::BITS_PER_LONG as usize) 265 + * bindings::BITS_PER_LONG as usize 266 + / 8, 267 + ); 268 + } 269 + } 270 + } 271 + 272 + impl Bitmap { 273 + /// Set bit with index `index`. 274 + /// 275 + /// ATTENTION: `set_bit` is non-atomic, which differs from the naming 276 + /// convention in C code. The corresponding C function is `__set_bit`. 277 + /// 278 + /// If CONFIG_RUST_BITMAP_HARDENED is not enabled and `index` is greater than 279 + /// or equal to `self.nbits`, does nothing. 280 + /// 281 + /// # Panics 282 + /// 283 + /// Panics if CONFIG_RUST_BITMAP_HARDENED is enabled and `index` is greater than 284 + /// or equal to `self.nbits`. 285 + #[inline] 286 + pub fn set_bit(&mut self, index: usize) { 287 + bitmap_assert_return!( 288 + index < self.len(), 289 + "Bit `index` must be < {}, was {}", 290 + self.len(), 291 + index 292 + ); 293 + // SAFETY: Bit `index` is within bounds. 294 + unsafe { bindings::__set_bit(index, self.as_mut_ptr()) }; 295 + } 296 + 297 + /// Set bit with index `index`, atomically. 298 + /// 299 + /// This is a relaxed atomic operation (no implied memory barriers). 300 + /// 301 + /// ATTENTION: The naming convention differs from C, where the corresponding 302 + /// function is called `set_bit`. 303 + /// 304 + /// If CONFIG_RUST_BITMAP_HARDENED is not enabled and `index` is greater than 305 + /// or equal to `self.len()`, does nothing. 306 + /// 307 + /// # Panics 308 + /// 309 + /// Panics if CONFIG_RUST_BITMAP_HARDENED is enabled and `index` is greater than 310 + /// or equal to `self.len()`. 311 + #[inline] 312 + pub fn set_bit_atomic(&self, index: usize) { 313 + bitmap_assert_return!( 314 + index < self.len(), 315 + "Bit `index` must be < {}, was {}", 316 + self.len(), 317 + index 318 + ); 319 + // SAFETY: `index` is within bounds and the caller has ensured that 320 + // there is no mix of non-atomic and atomic operations. 321 + unsafe { bindings::set_bit(index, self.as_ptr().cast_mut()) }; 322 + } 323 + 324 + /// Clear `index` bit. 325 + /// 326 + /// ATTENTION: `clear_bit` is non-atomic, which differs from the naming 327 + /// convention in C code. The corresponding C function is `__clear_bit`. 328 + /// 329 + /// If CONFIG_RUST_BITMAP_HARDENED is not enabled and `index` is greater than 330 + /// or equal to `self.len()`, does nothing. 331 + /// 332 + /// # Panics 333 + /// 334 + /// Panics if CONFIG_RUST_BITMAP_HARDENED is enabled and `index` is greater than 335 + /// or equal to `self.len()`. 336 + #[inline] 337 + pub fn clear_bit(&mut self, index: usize) { 338 + bitmap_assert_return!( 339 + index < self.len(), 340 + "Bit `index` must be < {}, was {}", 341 + self.len(), 342 + index 343 + ); 344 + // SAFETY: `index` is within bounds. 345 + unsafe { bindings::__clear_bit(index, self.as_mut_ptr()) }; 346 + } 347 + 348 + /// Clear `index` bit, atomically. 349 + /// 350 + /// This is a relaxed atomic operation (no implied memory barriers). 351 + /// 352 + /// ATTENTION: The naming convention differs from C, where the corresponding 353 + /// function is called `clear_bit`. 354 + /// 355 + /// If CONFIG_RUST_BITMAP_HARDENED is not enabled and `index` is greater than 356 + /// or equal to `self.len()`, does nothing. 357 + /// 358 + /// # Panics 359 + /// 360 + /// Panics if CONFIG_RUST_BITMAP_HARDENED is enabled and `index` is greater than 361 + /// or equal to `self.len()`. 362 + #[inline] 363 + pub fn clear_bit_atomic(&self, index: usize) { 364 + bitmap_assert_return!( 365 + index < self.len(), 366 + "Bit `index` must be < {}, was {}", 367 + self.len(), 368 + index 369 + ); 370 + // SAFETY: `index` is within bounds and the caller has ensured that 371 + // there is no mix of non-atomic and atomic operations. 372 + unsafe { bindings::clear_bit(index, self.as_ptr().cast_mut()) }; 373 + } 374 + 375 + /// Copy `src` into this [`Bitmap`] and set any remaining bits to zero. 376 + /// 377 + /// # Examples 378 + /// 379 + /// ``` 380 + /// use kernel::alloc::{AllocError, flags::GFP_KERNEL}; 381 + /// use kernel::bitmap::BitmapVec; 382 + /// 383 + /// let mut long_bitmap = BitmapVec::new(256, GFP_KERNEL)?; 384 + /// 385 + /// assert_eq!(None, long_bitmap.last_bit()); 386 + /// 387 + /// let mut short_bitmap = BitmapVec::new(16, GFP_KERNEL)?; 388 + /// 389 + /// short_bitmap.set_bit(7); 390 + /// long_bitmap.copy_and_extend(&short_bitmap); 391 + /// assert_eq!(Some(7), long_bitmap.last_bit()); 392 + /// 393 + /// # Ok::<(), AllocError>(()) 394 + /// ``` 395 + #[inline] 396 + pub fn copy_and_extend(&mut self, src: &Bitmap) { 397 + let len = core::cmp::min(src.len(), self.len()); 398 + // SAFETY: access to `self` and `src` is within bounds. 399 + unsafe { 400 + bindings::bitmap_copy_and_extend( 401 + self.as_mut_ptr(), 402 + src.as_ptr(), 403 + len as u32, 404 + self.len() as u32, 405 + ) 406 + }; 407 + } 408 + 409 + /// Finds last set bit. 410 + /// 411 + /// # Examples 412 + /// 413 + /// ``` 414 + /// use kernel::alloc::{AllocError, flags::GFP_KERNEL}; 415 + /// use kernel::bitmap::BitmapVec; 416 + /// 417 + /// let bitmap = BitmapVec::new(64, GFP_KERNEL)?; 418 + /// 419 + /// match bitmap.last_bit() { 420 + /// Some(idx) => { 421 + /// pr_info!("The last bit has index {idx}.\n"); 422 + /// } 423 + /// None => { 424 + /// pr_info!("All bits in this bitmap are 0.\n"); 425 + /// } 426 + /// } 427 + /// # Ok::<(), AllocError>(()) 428 + /// ``` 429 + #[inline] 430 + pub fn last_bit(&self) -> Option<usize> { 431 + // SAFETY: `_find_next_bit` access is within bounds due to invariant. 432 + let index = unsafe { bindings::_find_last_bit(self.as_ptr(), self.len()) }; 433 + if index >= self.len() { 434 + None 435 + } else { 436 + Some(index) 437 + } 438 + } 439 + 440 + /// Finds next set bit, starting from `start`. 441 + /// 442 + /// Returns `None` if `start` is greater or equal to `self.nbits`. 443 + #[inline] 444 + pub fn next_bit(&self, start: usize) -> Option<usize> { 445 + bitmap_assert!( 446 + start < self.len(), 447 + "`start` must be < {} was {}", 448 + self.len(), 449 + start 450 + ); 451 + // SAFETY: `_find_next_bit` tolerates out-of-bounds arguments and returns a 452 + // value larger than or equal to `self.len()` in that case. 453 + let index = unsafe { bindings::_find_next_bit(self.as_ptr(), self.len(), start) }; 454 + if index >= self.len() { 455 + None 456 + } else { 457 + Some(index) 458 + } 459 + } 460 + 461 + /// Finds next zero bit, starting from `start`. 462 + /// Returns `None` if `start` is greater than or equal to `self.len()`. 463 + #[inline] 464 + pub fn next_zero_bit(&self, start: usize) -> Option<usize> { 465 + bitmap_assert!( 466 + start < self.len(), 467 + "`start` must be < {} was {}", 468 + self.len(), 469 + start 470 + ); 471 + // SAFETY: `_find_next_zero_bit` tolerates out-of-bounds arguments and returns a 472 + // value larger than or equal to `self.len()` in that case. 473 + let index = unsafe { bindings::_find_next_zero_bit(self.as_ptr(), self.len(), start) }; 474 + if index >= self.len() { 475 + None 476 + } else { 477 + Some(index) 478 + } 479 + } 480 + } 481 + 482 + use macros::kunit_tests; 483 + 484 + #[kunit_tests(rust_kernel_bitmap)] 485 + mod tests { 486 + use super::*; 487 + use kernel::alloc::flags::GFP_KERNEL; 488 + 489 + #[test] 490 + fn bitmap_borrow() { 491 + let fake_bitmap: [usize; 2] = [0, 0]; 492 + // SAFETY: `fake_c_bitmap` is an array of expected length. 493 + let b = unsafe { Bitmap::from_raw(fake_bitmap.as_ptr(), 2 * BITS_PER_LONG) }; 494 + assert_eq!(2 * BITS_PER_LONG, b.len()); 495 + assert_eq!(None, b.next_bit(0)); 496 + } 497 + 498 + #[test] 499 + fn bitmap_copy() { 500 + let fake_bitmap: usize = 0xFF; 501 + // SAFETY: `fake_c_bitmap` can be used as one-element array of expected length. 502 + let b = unsafe { Bitmap::from_raw(core::ptr::addr_of!(fake_bitmap), 8) }; 503 + assert_eq!(8, b.len()); 504 + assert_eq!(None, b.next_zero_bit(0)); 505 + } 506 + 507 + #[test] 508 + fn bitmap_vec_new() -> Result<(), AllocError> { 509 + let b = BitmapVec::new(0, GFP_KERNEL)?; 510 + assert_eq!(0, b.len()); 511 + 512 + let b = BitmapVec::new(3, GFP_KERNEL)?; 513 + assert_eq!(3, b.len()); 514 + 515 + let b = BitmapVec::new(1024, GFP_KERNEL)?; 516 + assert_eq!(1024, b.len()); 517 + 518 + // Requesting too large values results in [`AllocError`]. 519 + let res = BitmapVec::new(1 << 31, GFP_KERNEL); 520 + assert!(res.is_err()); 521 + Ok(()) 522 + } 523 + 524 + #[test] 525 + fn bitmap_set_clear_find() -> Result<(), AllocError> { 526 + let mut b = BitmapVec::new(128, GFP_KERNEL)?; 527 + 528 + // Zero-initialized 529 + assert_eq!(None, b.next_bit(0)); 530 + assert_eq!(Some(0), b.next_zero_bit(0)); 531 + assert_eq!(None, b.last_bit()); 532 + 533 + b.set_bit(17); 534 + 535 + assert_eq!(Some(17), b.next_bit(0)); 536 + assert_eq!(Some(17), b.next_bit(17)); 537 + assert_eq!(None, b.next_bit(18)); 538 + assert_eq!(Some(17), b.last_bit()); 539 + 540 + b.set_bit(107); 541 + 542 + assert_eq!(Some(17), b.next_bit(0)); 543 + assert_eq!(Some(17), b.next_bit(17)); 544 + assert_eq!(Some(107), b.next_bit(18)); 545 + assert_eq!(Some(107), b.last_bit()); 546 + 547 + b.clear_bit(17); 548 + 549 + assert_eq!(Some(107), b.next_bit(0)); 550 + assert_eq!(Some(107), b.last_bit()); 551 + Ok(()) 552 + } 553 + 554 + #[test] 555 + fn owned_bitmap_out_of_bounds() -> Result<(), AllocError> { 556 + // TODO: Kunit #[test]s do not support `cfg` yet, 557 + // so we add it here in the body. 558 + #[cfg(not(CONFIG_RUST_BITMAP_HARDENED))] 559 + { 560 + let mut b = BitmapVec::new(128, GFP_KERNEL)?; 561 + b.set_bit(2048); 562 + b.set_bit_atomic(2048); 563 + b.clear_bit(2048); 564 + b.clear_bit_atomic(2048); 565 + assert_eq!(None, b.next_bit(2048)); 566 + assert_eq!(None, b.next_zero_bit(2048)); 567 + assert_eq!(None, b.last_bit()); 568 + } 569 + Ok(()) 570 + } 571 + 572 + // TODO: uncomment once kunit supports [should_panic] and `cfg`. 573 + // #[cfg(CONFIG_RUST_BITMAP_HARDENED)] 574 + // #[test] 575 + // #[should_panic] 576 + // fn owned_bitmap_out_of_bounds() -> Result<(), AllocError> { 577 + // let mut b = BitmapVec::new(128, GFP_KERNEL)?; 578 + // 579 + // b.set_bit(2048); 580 + // } 581 + 582 + #[test] 583 + fn bitmap_copy_and_extend() -> Result<(), AllocError> { 584 + let mut long_bitmap = BitmapVec::new(256, GFP_KERNEL)?; 585 + 586 + long_bitmap.set_bit(3); 587 + long_bitmap.set_bit(200); 588 + 589 + let mut short_bitmap = BitmapVec::new(32, GFP_KERNEL)?; 590 + 591 + short_bitmap.set_bit(17); 592 + 593 + long_bitmap.copy_and_extend(&short_bitmap); 594 + 595 + // Previous bits have been cleared. 596 + assert_eq!(Some(17), long_bitmap.next_bit(0)); 597 + assert_eq!(Some(17), long_bitmap.last_bit()); 598 + Ok(()) 599 + } 600 + }
+226
rust/kernel/id_pool.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + // Copyright (C) 2025 Google LLC. 4 + 5 + //! Rust API for an ID pool backed by a [`BitmapVec`]. 6 + 7 + use crate::alloc::{AllocError, Flags}; 8 + use crate::bitmap::BitmapVec; 9 + 10 + const BITS_PER_LONG: usize = bindings::BITS_PER_LONG as usize; 11 + 12 + /// Represents a dynamic ID pool backed by a [`BitmapVec`]. 13 + /// 14 + /// Clients acquire and release IDs from unset bits in a bitmap. 15 + /// 16 + /// The capacity of the ID pool may be adjusted by users as 17 + /// needed. The API supports the scenario where users need precise control 18 + /// over the time of allocation of a new backing bitmap, which may require 19 + /// release of spinlock. 20 + /// Due to concurrent updates, all operations are re-verified to determine 21 + /// if the grow or shrink is sill valid. 22 + /// 23 + /// # Examples 24 + /// 25 + /// Basic usage 26 + /// 27 + /// ``` 28 + /// use kernel::alloc::{AllocError, flags::GFP_KERNEL}; 29 + /// use kernel::id_pool::IdPool; 30 + /// 31 + /// let mut pool = IdPool::new(64, GFP_KERNEL)?; 32 + /// for i in 0..64 { 33 + /// assert_eq!(i, pool.acquire_next_id(i).ok_or(ENOSPC)?); 34 + /// } 35 + /// 36 + /// pool.release_id(23); 37 + /// assert_eq!(23, pool.acquire_next_id(0).ok_or(ENOSPC)?); 38 + /// 39 + /// assert_eq!(None, pool.acquire_next_id(0)); // time to realloc. 40 + /// let resizer = pool.grow_request().ok_or(ENOSPC)?.realloc(GFP_KERNEL)?; 41 + /// pool.grow(resizer); 42 + /// 43 + /// assert_eq!(pool.acquire_next_id(0), Some(64)); 44 + /// # Ok::<(), Error>(()) 45 + /// ``` 46 + /// 47 + /// Releasing spinlock to grow the pool 48 + /// 49 + /// ```no_run 50 + /// use kernel::alloc::{AllocError, flags::GFP_KERNEL}; 51 + /// use kernel::sync::{new_spinlock, SpinLock}; 52 + /// use kernel::id_pool::IdPool; 53 + /// 54 + /// fn get_id_maybe_realloc(guarded_pool: &SpinLock<IdPool>) -> Result<usize, AllocError> { 55 + /// let mut pool = guarded_pool.lock(); 56 + /// loop { 57 + /// match pool.acquire_next_id(0) { 58 + /// Some(index) => return Ok(index), 59 + /// None => { 60 + /// let alloc_request = pool.grow_request(); 61 + /// drop(pool); 62 + /// let resizer = alloc_request.ok_or(AllocError)?.realloc(GFP_KERNEL)?; 63 + /// pool = guarded_pool.lock(); 64 + /// pool.grow(resizer) 65 + /// } 66 + /// } 67 + /// } 68 + /// } 69 + /// ``` 70 + pub struct IdPool { 71 + map: BitmapVec, 72 + } 73 + 74 + /// Indicates that an [`IdPool`] should change to a new target size. 75 + pub struct ReallocRequest { 76 + num_ids: usize, 77 + } 78 + 79 + /// Contains a [`BitmapVec`] of a size suitable for reallocating [`IdPool`]. 80 + pub struct PoolResizer { 81 + new: BitmapVec, 82 + } 83 + 84 + impl ReallocRequest { 85 + /// Allocates a new backing [`BitmapVec`] for [`IdPool`]. 86 + /// 87 + /// This method only prepares reallocation and does not complete it. 88 + /// Reallocation will complete after passing the [`PoolResizer`] to the 89 + /// [`IdPool::grow`] or [`IdPool::shrink`] operation, which will check 90 + /// that reallocation still makes sense. 91 + pub fn realloc(&self, flags: Flags) -> Result<PoolResizer, AllocError> { 92 + let new = BitmapVec::new(self.num_ids, flags)?; 93 + Ok(PoolResizer { new }) 94 + } 95 + } 96 + 97 + impl IdPool { 98 + /// Constructs a new [`IdPool`]. 99 + /// 100 + /// A capacity below [`BITS_PER_LONG`] is adjusted to 101 + /// [`BITS_PER_LONG`]. 102 + /// 103 + /// [`BITS_PER_LONG`]: srctree/include/asm-generic/bitsperlong.h 104 + #[inline] 105 + pub fn new(num_ids: usize, flags: Flags) -> Result<Self, AllocError> { 106 + let num_ids = core::cmp::max(num_ids, BITS_PER_LONG); 107 + let map = BitmapVec::new(num_ids, flags)?; 108 + Ok(Self { map }) 109 + } 110 + 111 + /// Returns how many IDs this pool can currently have. 112 + #[inline] 113 + pub fn capacity(&self) -> usize { 114 + self.map.len() 115 + } 116 + 117 + /// Returns a [`ReallocRequest`] if the [`IdPool`] can be shrunk, [`None`] otherwise. 118 + /// 119 + /// The capacity of an [`IdPool`] cannot be shrunk below [`BITS_PER_LONG`]. 120 + /// 121 + /// [`BITS_PER_LONG`]: srctree/include/asm-generic/bitsperlong.h 122 + /// 123 + /// # Examples 124 + /// 125 + /// ``` 126 + /// use kernel::alloc::{AllocError, flags::GFP_KERNEL}; 127 + /// use kernel::id_pool::{ReallocRequest, IdPool}; 128 + /// 129 + /// let mut pool = IdPool::new(1024, GFP_KERNEL)?; 130 + /// let alloc_request = pool.shrink_request().ok_or(AllocError)?; 131 + /// let resizer = alloc_request.realloc(GFP_KERNEL)?; 132 + /// pool.shrink(resizer); 133 + /// assert_eq!(pool.capacity(), kernel::bindings::BITS_PER_LONG as usize); 134 + /// # Ok::<(), AllocError>(()) 135 + /// ``` 136 + #[inline] 137 + pub fn shrink_request(&self) -> Option<ReallocRequest> { 138 + let cap = self.capacity(); 139 + // Shrinking below [`BITS_PER_LONG`] is never possible. 140 + if cap <= BITS_PER_LONG { 141 + return None; 142 + } 143 + // Determine if the bitmap can shrink based on the position of 144 + // its last set bit. If the bit is within the first quarter of 145 + // the bitmap then shrinking is possible. In this case, the 146 + // bitmap should shrink to half its current size. 147 + let Some(bit) = self.map.last_bit() else { 148 + return Some(ReallocRequest { 149 + num_ids: BITS_PER_LONG, 150 + }); 151 + }; 152 + if bit >= (cap / 4) { 153 + return None; 154 + } 155 + let num_ids = usize::max(BITS_PER_LONG, cap / 2); 156 + Some(ReallocRequest { num_ids }) 157 + } 158 + 159 + /// Shrinks pool by using a new [`BitmapVec`], if still possible. 160 + #[inline] 161 + pub fn shrink(&mut self, mut resizer: PoolResizer) { 162 + // Between request to shrink that led to allocation of `resizer` and now, 163 + // bits may have changed. 164 + // Verify that shrinking is still possible. In case shrinking to 165 + // the size of `resizer` is no longer possible, do nothing, 166 + // drop `resizer` and move on. 167 + let Some(updated) = self.shrink_request() else { 168 + return; 169 + }; 170 + if updated.num_ids > resizer.new.len() { 171 + return; 172 + } 173 + 174 + resizer.new.copy_and_extend(&self.map); 175 + self.map = resizer.new; 176 + } 177 + 178 + /// Returns a [`ReallocRequest`] for growing this [`IdPool`], if possible. 179 + /// 180 + /// The capacity of an [`IdPool`] cannot be grown above [`i32::MAX`]. 181 + #[inline] 182 + pub fn grow_request(&self) -> Option<ReallocRequest> { 183 + let num_ids = self.capacity() * 2; 184 + if num_ids > i32::MAX.try_into().unwrap() { 185 + return None; 186 + } 187 + Some(ReallocRequest { num_ids }) 188 + } 189 + 190 + /// Grows pool by using a new [`BitmapVec`], if still necessary. 191 + /// 192 + /// The `resizer` arguments has to be obtained by calling [`Self::grow_request`] 193 + /// on this object and performing a [`ReallocRequest::realloc`]. 194 + #[inline] 195 + pub fn grow(&mut self, mut resizer: PoolResizer) { 196 + // Between request to grow that led to allocation of `resizer` and now, 197 + // another thread may have already grown the capacity. 198 + // In this case, do nothing, drop `resizer` and move on. 199 + if resizer.new.len() <= self.capacity() { 200 + return; 201 + } 202 + 203 + resizer.new.copy_and_extend(&self.map); 204 + self.map = resizer.new; 205 + } 206 + 207 + /// Acquires a new ID by finding and setting the next zero bit in the 208 + /// bitmap. 209 + /// 210 + /// Upon success, returns its index. Otherwise, returns [`None`] 211 + /// to indicate that a [`Self::grow_request`] is needed. 212 + #[inline] 213 + pub fn acquire_next_id(&mut self, offset: usize) -> Option<usize> { 214 + let next_zero_bit = self.map.next_zero_bit(offset); 215 + if let Some(nr) = next_zero_bit { 216 + self.map.set_bit(nr); 217 + } 218 + next_zero_bit 219 + } 220 + 221 + /// Releases an ID. 222 + #[inline] 223 + pub fn release_id(&mut self, id: usize) { 224 + self.map.clear_bit(id); 225 + } 226 + }
+2
rust/kernel/lib.rs
··· 64 64 pub mod alloc; 65 65 #[cfg(CONFIG_AUXILIARY_BUS)] 66 66 pub mod auxiliary; 67 + pub mod bitmap; 67 68 pub mod bits; 68 69 #[cfg(CONFIG_BLOCK)] 69 70 pub mod block; ··· 93 92 pub mod firmware; 94 93 pub mod fmt; 95 94 pub mod fs; 95 + pub mod id_pool; 96 96 pub mod init; 97 97 pub mod io; 98 98 pub mod ioctl;
+10
security/Kconfig.hardening
··· 255 255 256 256 If unsure, say N. 257 257 258 + config RUST_BITMAP_HARDENED 259 + bool "Check integrity of bitmap Rust API" 260 + depends on RUST 261 + help 262 + Enables additional assertions in the Rust Bitmap API to catch 263 + arguments that are not guaranteed to result in an immediate access 264 + fault. 265 + 266 + If unsure, say N. 267 + 258 268 config BUG_ON_DATA_CORRUPTION 259 269 bool "Trigger a BUG when data corruption is detected" 260 270 select LIST_HARDENED
+3 -1
sound/soc/rockchip/rockchip_i2s_tdm.h
··· 10 10 #ifndef _ROCKCHIP_I2S_TDM_H 11 11 #define _ROCKCHIP_I2S_TDM_H 12 12 13 + #include <linux/hw_bitfield.h> 14 + 13 15 /* 14 16 * TXCR 15 17 * transmit operation control register ··· 287 285 #define I2S_TDM_RXCR (0x0034) 288 286 #define I2S_CLKDIV (0x0038) 289 287 290 - #define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK((h), (l)) << 16)) 288 + #define HIWORD_UPDATE(v, h, l) (FIELD_PREP_WM16_CONST(GENMASK((h), (l)), (v))) 291 289 292 290 /* PX30 GRF CONFIGS */ 293 291 #define PX30_I2S0_CLK_IN_SRC_FROM_TX HIWORD_UPDATE(1, 13, 12)