Hi Christophe, On Thu, 16 Mar 2023 14:00:42 +0000 Christophe Leroy <christophe.leroy@xxxxxxxxxx> wrote: [...] > > +#define PEF2256_PC6 0x86 /* Port Configuration 6 */ > > +#define PEF2256_GCM(_n) (0x92 + _n - 1) /* Global Counter Mode n=1..8 */ > > Should be (0x92 + (_n) - 1) to avoid any risk. Yes definitively. Will be updated in v3. > > > +#define PEF2256_GCM1 0x92 /* Global Counter Mode 1 */ [...] > > +#define PEF2256_GIS_ISR(_n) (1<<(n)) > > _n or n ? Should be (1 << (_n)) Will be updated in v3. > > > +#define PEF2256_WID 0xEC /* Wafer Identification Register */ [...] > > +static inline void pef2256_clrbits8(struct pef2256 *pef2256, int offset, u8 clr) > > +{ > > + u8 v; > > + > > + v = pef2256_read8(pef2256, offset); > > + v &= ~clr; > > + pef2256_write8(pef2256, offset, v); > > +} > > Not sure it is worth the number of lines. > > Would liekly be as good with just: > > pef2256_write8(pef2256, offset, pef2256_read8(pef2256, offset) & ~clr); > > Same for all. Will be updated in v3. > > > Also, it shouldn't need to be flagged 'inline' as it is defined in the C > file it is used. GCC will decide by itself if it is worth inlining. In the kernel register accessor helpers are traditionally inline. # git grep 'static .* u32 .*read.*(' drivers/*.c | grep inline | wc -l 432 # git grep 'static .* u32 .*read.*(' drivers/*.c | grep -v inline | wc -l 1 Sure, my git grep is not accurate but it gives ideas of the quantities. I prefer to keep the inline for the register accessor helpers. > > > + > > +static inline void pef2256_setbits8(struct pef2256 *pef2256, int offset, u8 set) > > +{ > > + u8 v; > > + > > + v = pef2256_read8(pef2256, offset); > > + v |= set; > > + pef2256_write8(pef2256, offset, v); > > +} > > + > > + > > +static inline void pef2256_clrsetbits8(struct pef2256 *pef2256, int offset, u8 clr, u8 set) > > +{ > > + u8 v; > > + > > + v = pef2256_read8(pef2256, offset); > > + v &= ~clr; > > + v |= set; > > + pef2256_write8(pef2256, offset, v); > > +} > > + > > +static enum pef2256_version pef2256_get_version(struct pef2256 *pef2256) > > +{ > > + enum pef2256_version version; > > + const char *version_txt; > > + u8 vstr, wid; > > + > > + vstr = pef2256_read8(pef2256, PEF2256_VSTR); > > + wid = pef2256_read8(pef2256, PEF2256_WID); > > + > > + switch (vstr) { > > + case PEF2256_VSTR_VERSION_12: > > + if ((wid & PEF2256_12_WID_MASK) == PEF2256_12_WID_VERSION_12) { > > + version_txt = "1.2"; > > + version = PEF2256_VERSION_1_2; > > + goto end; > > + } > > + break; > > + case PEF2256_VSTR_VERSION_2x: > > + switch (wid & PEF2256_2X_WID_MASK) { > > + case PEF2256_2X_WID_VERSION_21: > > + version_txt = "2.1 (2.x)"; > > + version = PEF2256_VERSION_2_1; > > + goto end; > > + case PEF2256_2X_WID_VERSION_22: > > + version_txt = "2.2 (2.x)"; > > + version = PEF2256_VERSION_2_2; > > + goto end; > > + default: > > + break; > > + } > > + break; > > + case PEF2256_VSTR_VERSION_21: > > + version_txt = "2.1"; > > + version = PEF2256_VERSION_2_1; > > + goto end; > > + default: > > + break; > > A default doing nothing is not needed unless the switch handles a enum > and you have not covered all possible values. > > My preference would be that you use the default to set: > version = PEF2256_VERSION_UNKNOWN; > > then use an if (version == PEF2256_VERSION_UNKNOWN) / else below for the > dev_err/dev_info. The function will be reworked in v3 > > > + } > > + > > + dev_err(pef2256->dev, "Unknown version (0x%02x, 0x%02x)\n", vstr, wid); > > + return PEF2256_VERSION_UNKNOWN; > > + > > +end: > > + dev_info(pef2256->dev, "Version %s detected\n", version_txt); > > + return version; > > +} > > + > > +static int pef2256_12_setup_gcm(struct pef2256 *pef2256) > > +{ > > + static const u8 gcm_1544000[6] = {0xF0, 0x51, 0x00, 0x80, 0x00, 0x15}; > > + static const u8 gcm_2048000[6] = {0x00, 0x58, 0xD2, 0xC2, 0x00, 0x10}; > > + static const u8 gcm_8192000[6] = {0x00, 0x58, 0xD2, 0xC2, 0x03, 0x10}; > > + static const u8 gcm_10000000[6] = {0x90, 0x51, 0x81, 0x8F, 0x04, 0x10}; > > + static const u8 gcm_12352000[6] = {0xF0, 0x51, 0x00, 0x80, 0x07, 0x15}; > > + static const u8 gcm_16384000[6] = {0x00, 0x58, 0xD2, 0xC2, 0x07, 0x10}; > > + unsigned long mclk_rate; > > + const u8 *gcm; > > + int i; > > + > > + mclk_rate = clk_get_rate(pef2256->mclk); > > + switch (mclk_rate) { > > + case 1544000: > > + gcm = gcm_1544000; > > + break; > > + case 2048000: > > + gcm = gcm_2048000; > > + break; > > + case 8192000: > > + gcm = gcm_8192000; > > + break; > > + case 10000000: > > + gcm = gcm_10000000; > > + break; > > + case 12352000: > > + gcm = gcm_12352000; > > + break; > > + case 16384000: > > + gcm = gcm_16384000; > > + break; > > + default: > > + dev_err(pef2256->dev, "Unsupported v1.2 MCLK rate %lu\n", mclk_rate); > > + return -EINVAL; > > + } > > + for (i = 0; i < 6; i++) > > + pef2256_write8(pef2256, PEF2256_GCM(i+1), gcm[i]); > > + > > + return 0; > > +} > > + > > +static int pef2256_2x_setup_gcm(struct pef2256 *pef2256) > > +{ > > + static const u8 gcm_1544000[8] = {0x00, 0x15, 0x00, 0x08, 0x00, 0x3F, 0x9C, 0xDF}; > > + static const u8 gcm_2048000[8] = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x2F, 0xDB, 0xDF}; > > + static const u8 gcm_8192000[8] = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x0B, 0xDB, 0xDF}; > > + static const u8 gcm_10000000[8] = {0x40, 0x1B, 0x3D, 0x0A, 0x00, 0x07, 0xC9, 0xDC}; > > + static const u8 gcm_12352000[8] = {0x00, 0x19, 0x00, 0x08, 0x01, 0x0A, 0x98, 0xDA}; > > + static const u8 gcm_16384000[8] = {0x00, 0x18, 0xFB, 0x0B, 0x01, 0x0B, 0xDB, 0xDF}; > > + unsigned long mclk_rate; > > + const u8 *gcm; > > + int i; > > + > > + mclk_rate = clk_get_rate(pef2256->mclk); > > + switch (mclk_rate) { > > + case 1544000: > > + gcm = gcm_1544000; > > + break; > > + case 2048000: > > + gcm = gcm_2048000; > > + break; > > + case 8192000: > > + gcm = gcm_8192000; > > + break; > > + case 10000000: > > + gcm = gcm_10000000; > > + break; > > + case 12352000: > > + gcm = gcm_12352000; > > + break; > > + case 16384000: > > + gcm = gcm_16384000; > > + break; > > + default: > > + dev_err(pef2256->dev, "Unsupported v2.x MCLK rate %lu\n", mclk_rate); > > + return -EINVAL; > > + } > > + for (i = 0; i < 8; i++) > > + pef2256_write8(pef2256, PEF2256_GCM(i+1), gcm[i]); > > + > > + return 0; > > +} > > This function and the previous one look very similar, can we merge them ? Yes, will be merged in v3. > > > + > > +static int pef2256_setup_gcm(struct pef2256 *pef2256) > > +{ > > + return (pef2256->version == PEF2256_VERSION_1_2) ? > > + pef2256_12_setup_gcm(pef2256) : pef2256_2x_setup_gcm(pef2256); > > +} > > + > > +static int pef2256_setup_e1(struct pef2256 *pef2256) > > +{ > > + u8 fmr1, fmr2, sic1; > > + int ret; > > + > > + /* Basic setup, Master clocking mode (GCM8..1) */ > > + ret = pef2256_setup_gcm(pef2256); > > + if (ret) > > + return ret; > > + > > + /* RCLK output : DPLL clock, DCO-X enabled, DCO-X internal ref clock */ > > + pef2256_write8(pef2256, PEF2256_CMR1, 0x00); > > + > > + /* > > + * SCLKR selected, SCLKX selected, > > + * receive synchro pulse sourced by SYPR, > > + * transmit synchro pulse sourced by SYPX > > + */ > > + pef2256_write8(pef2256, PEF2256_CMR2, 0x00); > > + > > + /* NRZ coding, no alarm simulation */ > > + pef2256_write8(pef2256, PEF2256_FMR0, 0x00); > > + > > + /* > > + * E1, frame format, 2 Mbit/s system data rate, no AIS > > + * transmission to remote end or system interface, payload loop > > + * off, transmit remote alarm on > > + */ > > + fmr1 = 0x00; > > + fmr2 = PEF2256_FMR2_AXRA; > > + switch (pef2256->frame_type) { > > + case PEF2256_FRAME_E1_DOUBLEFRAME: > > + fmr2 |= PEF2256_FMR2_RFS_DOUBLEFRAME; > > + break; > > + case PEF2256_FRAME_E1_CRC4_MULTIFRAME: > > + fmr1 |= PEF2256_FMR1_XFS; > > + fmr2 |= PEF2256_FMR2_RFS_CRC4_MULTIFRAME; > > + break; > > + case PEF2256_FRAME_E1_AUTO_MULTIFRAME: > > + fmr1 |= PEF2256_FMR1_XFS; > > + fmr2 |= PEF2256_FMR2_RFS_AUTO_MULTIFRAME; > > + break; > > + default: > > + dev_err(pef2256->dev, "Unsupported frame type %d\n", pef2256->frame_type); > > + return -EINVAL; > > + } > > + pef2256_write8(pef2256, PEF2256_FMR1, fmr1); > > + pef2256_write8(pef2256, PEF2256_FMR2, fmr2); > > + > > + /* E1 default for the receive slicer threshold */ > > + pef2256_write8(pef2256, PEF2256_LIM2, PEF2256_LIM2_SLT_THR50); > > + if (!pef2256->is_subordinate) { > > + /* SEC input, active high */ > > + pef2256_write8(pef2256, PEF2256_GPC1, PEF2256_GPC1_CSFP_SEC_IN_HIGH); > > + } else { > > + /* Loop-timed */ > > + pef2256_setbits8(pef2256, PEF2256_LIM2, PEF2256_LIM2_ELT); > > + /* FSC output, active high */ > > + pef2256_write8(pef2256, PEF2256_GPC1, PEF2256_GPC1_CSFP_FSC_OUT_HIGH); > > + } > > + > > + /* internal second timer, power on */ > > + pef2256_write8(pef2256, PEF2256_GCR, 0x00); > > + > > + /* > > + * slave mode, local loop off, mode short-haul > > + * In v2.x, bit3 is a forced 1 bit in the datasheet -> Need to be set. > > + */ > > + if (pef2256->version == PEF2256_VERSION_1_2) > > + pef2256_write8(pef2256, PEF2256_LIM0, 0x00); > > + else > > + pef2256_write8(pef2256, PEF2256_LIM0, PEF2256_2X_LIM0_BIT3); > > + > > + /* analog interface selected, remote loop off */ > > + pef2256_write8(pef2256, PEF2256_LIM1, 0x00); > > + > > + /* > > + * SCLKR, SCLKX, RCLK configured to inputs, > > + * XFMS active low, CLK1 and CLK2 pin configuration > > + */ > > + pef2256_write8(pef2256, PEF2256_PC5, 0x00); > > + pef2256_write8(pef2256, PEF2256_PC6, 0x00); > > + > > + /* > > + * 2.048 MHz system clocking rate, receive buffer 2 frames, transmit > > + * buffer bypass, data sampled and transmitted on the falling edge of > > + * SCLKR/X, automatic freeze signaling, data is active in the first > > + * channel phase > > + */ > > + pef2256_write8(pef2256, PEF2256_SIC1, 0x00); > > + pef2256_write8(pef2256, PEF2256_SIC2, 0x00); > > + pef2256_write8(pef2256, PEF2256_SIC3, 0x00); > > + > > + /* channel loop-back and single frame mode are disabled */ > > + pef2256_write8(pef2256, PEF2256_LOOP, 0x00); > > + > > + /* all bits of the transmitted service word are cleared */ > > + pef2256_write8(pef2256, PEF2256_XSW, PEF2256_XSW_XY(0x1F)); > > + /* CAS disabled and clear spare bit values */ > > + pef2256_write8(pef2256, PEF2256_XSP, 0x00); > > + > > + /* no transparent mode active */ > > + pef2256_write8(pef2256, PEF2256_TSWM, 0x00); > > + > > + /* > > + * the transmit clock offset is cleared > > + * the transmit time slot offset is cleared > > + */ > > + pef2256_write8(pef2256, PEF2256_XC0, 0x00); > > + > > + /* Keep default value for the transmit offset */ > > + pef2256_write8(pef2256, PEF2256_XC1, 0x9C); > > + > > + /* > > + * transmit pulse mask, default value from datasheet > > + * transmitter in tristate mode > > + */ > > + if (pef2256->version == PEF2256_VERSION_1_2) { > > + pef2256_write8(pef2256, PEF2256_XPM0, 0x7B); > > + pef2256_write8(pef2256, PEF2256_XPM1, 0x03); > > + pef2256_write8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT | 0x00); > > + } else { > > + pef2256_write8(pef2256, PEF2256_XPM0, 0x9C); > > + pef2256_write8(pef2256, PEF2256_XPM1, 0x03); > > + pef2256_write8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT | 0x00); > > + } > > Only first line seem different, could XPM1 and XPM2 be outside the if/else ? Sure. Will be updated in v3. > > > + > > + /* "master" mode */ > > + if (!pef2256->is_subordinate) > > + pef2256_setbits8(pef2256, PEF2256_LIM0, PEF2256_LIM0_MAS); > > + > > + /* transmit line in normal operation */ > > + pef2256_clrbits8(pef2256, PEF2256_XPM2, PEF2256_XPM2_XLT); > > + > > + if (pef2256->version == PEF2256_VERSION_1_2) { > > + /* receive input threshold = 0,21V */ > > + pef2256_clrsetbits8(pef2256, PEF2256_LIM1, PEF2256_12_LIM1_RIL_MASK, > > + PEF2256_12_LIM1_RIL_210); > > + } else { > > + /* receive input threshold = 0,21V */ > > Same comment twice, could be before the 'if' and remove the { } then ? Will be updated in v3. > > > + pef2256_clrsetbits8(pef2256, PEF2256_LIM1, PEF2256_2X_LIM1_RIL_MASK, > > + PEF2256_2X_LIM1_RIL_210); > > + } > > + /* transmit line coding = HDB3 */ > > + pef2256_clrsetbits8(pef2256, PEF2256_FMR0, PEF2256_FMR0_XC_MASK, > > + PEF2256_FMR0_XC_HDB3); > > Wouldn't that fit in a single line with the new recommended 100 char max > line length ? I thing it would be more readable as a single line. Will be updated in v3 if it fits in 100 chars. Same for the line right below related to the receive part. > > > + > > + /* receive line coding = HDB3 */ > > + pef2256_clrsetbits8(pef2256, PEF2256_FMR0, PEF2256_FMR0_RC_MASK, > > + PEF2256_FMR0_RC_HDB3); > > + > > + /* detection of LOS alarm = 176 pulses (ie (10 + 1) * 16) */ > > + pef2256_write8(pef2256, PEF2256_PCD, 10); > > + > > + /* recovery of LOS alarm = 22 pulses (ie 21 + 1) */ > > + pef2256_write8(pef2256, PEF2256_PCR, 21); > > + > > + /* DCO-X center frequency enabled */ > > + pef2256_setbits8(pef2256, PEF2256_CMR2, PEF2256_CMR2_DCOXC); > > + > > + if (pef2256->is_subordinate) { > > + /* select RCLK source = 2M */ > > + pef2256_clrsetbits8(pef2256, PEF2256_CMR1, PEF2256_CMR1_RS_MASK, > > + PEF2256_CMR1_RS_DCOR_2048); > > + /* disable switching from RCLK to SYNC */ > > + pef2256_setbits8(pef2256, PEF2256_CMR1, PEF2256_CMR1_DCS); > > + } > > I'd move the comments into a single one before the 'if', the two > comments are related. I will change to a single line comment but not before the 'if'. The comment is related to the subordinate case and not global for 'all' cases. > > > + > > + if (pef2256->version != PEF2256_VERSION_1_2) { > > + /* during inactive channel phase switch RDO/RSIG into tri-state */ > > + pef2256_setbits8(pef2256, PEF2256_SIC3, PEF2256_SIC3_RTRI); > > + } > > I'd put the comment before the 'if' and remove the { } Same reason to keep as it. The comment is specific to the if content. > > > + > > + if (!pef2256->is_tx_falling_edge) { > > + /* rising edge sync pulse transmit */ > > This comment doesn't seem to match the condition (rising versus falling). if not falling, it is rising. I will update in v3 to invert the condition and improve the comment by mentioning transmit and receive in each cases. > > > + pef2256_clrsetbits8(pef2256, PEF2256_SIC3, > > + PEF2256_SIC3_RESR, PEF2256_SIC3_RESX); > > + } else { > > + /* rising edge sync pulse receive */ > > This comment doesn't seem to match the condition (receive versus tx). > > > + pef2256_clrsetbits8(pef2256, PEF2256_SIC3, > > + PEF2256_SIC3_RESX, PEF2256_SIC3_RESR); > > + } > > + > > + /* transmit offset counter (XCO10..0) = 4 */ > > + pef2256_write8(pef2256, PEF2256_XC0, 0); > > + pef2256_write8(pef2256, PEF2256_XC1, 4); > > + /* receive offset counter (RCO10..0) = 4 */ > > + pef2256_write8(pef2256, PEF2256_RC0, 0); > > + pef2256_write8(pef2256, PEF2256_RC1, 4); > > + > > + /* system clock rate */ > > + switch (pef2256->sysclk_rate) { > > + case 2048000: > > + sic1 = PEF2256_SIC1_SSC_2048; > > + break; > > + case 4096000: > > + sic1 = PEF2256_SIC1_SSC_4096; > > + break; > > + case 8192000: > > + sic1 = PEF2256_SIC1_SSC_8192; > > + break; > > + case 16384000: > > + sic1 = PEF2256_SIC1_SSC_16384; > > + break; > > + default: > > + dev_err(pef2256->dev, "Unsupported sysclk rate %u\n", pef2256->sysclk_rate); > > + return -EINVAL; > > + } > > + pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_SSC_MASK, sic1); > > + > > + /* data clock rate */ > > + switch (pef2256->data_rate) { > > + case 2048000: > > + fmr1 = PEF2256_FMR1_SSD_2048; > > + sic1 = PEF2256_SIC1_SSD_2048; > > + break; > > + case 4096000: > > + fmr1 = PEF2256_FMR1_SSD_4096; > > + sic1 = PEF2256_SIC1_SSD_4096; > > + break; > > + case 8192000: > > + fmr1 = PEF2256_FMR1_SSD_8192; > > + sic1 = PEF2256_SIC1_SSD_8192; > > + break; > > + case 16384000: > > + fmr1 = PEF2256_FMR1_SSD_16384; > > + sic1 = PEF2256_SIC1_SSD_16384; > > + break; > > + default: > > + dev_err(pef2256->dev, "Unsupported data rate %u\n", pef2256->data_rate); > > + return -EINVAL; > > + } > > + pef2256_clrsetbits8(pef2256, PEF2256_FMR1, PEF2256_FMR1_SSD_MASK, fmr1); > > + pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_SSD_MASK, sic1); > > + > > + /* channel phase */ > > + pef2256_clrsetbits8(pef2256, PEF2256_SIC2, PEF2256_SIC2_SICS_MASK, > > + PEF2256_SIC2_SICS(pef2256->channel_phase)); > > + > > + if (pef2256->is_subordinate) { > > + /* transmit buffer size = 2 frames */ > > + pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_XBS_MASK, > > + PEF2256_SIC1_XBS_2FRAMES); > > + /* transmit transparent mode */ > > + pef2256_setbits8(pef2256, PEF2256_XSW, PEF2256_XSW_XTM); > > + } > > Could this block get regrouped with the RX block depending on > is_subordinate ? Yes, Will be done in v3. > > > + > > + /* error counter latched every 1s */ > > + pef2256_setbits8(pef2256, PEF2256_FMR1, PEF2256_FMR1_ECM); > > + /* error counter mode COFA */ > > + pef2256_setbits8(pef2256, PEF2256_GCR, PEF2256_GCR_ECMC); > > + /* errors in service words have no influence */ > > + pef2256_setbits8(pef2256, PEF2256_RC0, PEF2256_RC0_SWD); > > + /* 4 consecutive incorrect FAS causes loss of sync */ > > + pef2256_setbits8(pef2256, PEF2256_RC0, PEF2256_RC0_ASY4); > > + /* Si-Bit, Spare bit For International, FAS word */ > > + pef2256_setbits8(pef2256, PEF2256_XSW, PEF2256_XSW_XSIS); > > + pef2256_setbits8(pef2256, PEF2256_XSP, PEF2256_XSP_XSIF); > > + > > + /* port RCLK is output */ > > + pef2256_setbits8(pef2256, PEF2256_PC5, PEF2256_PC5_CRP); > > + /* status changed interrupt at both up and down */ > > + pef2256_setbits8(pef2256, PEF2256_GCR, PEF2256_GCR_SCI); > > + > > + /* Clear any ISR2 pending interrupts and unmask needed interrupts */ > > + pef2256_read8(pef2256, PEF2256_ISR2); > > + pef2256_clrbits8(pef2256, PEF2256_IMR2, PEF2256_INT2_LOS | PEF2256_INT2_AIS); > > + > > + /* reset lines */ > > + pef2256_write8(pef2256, PEF2256_CMDR, PEF2256_CMDR_RRES | PEF2256_CMDR_XRES); > > + return 0; > > +} > > + > > +static int pef2256_setup(struct pef2256 *pef2256) > > +{ > > + if (!pef2256->is_e1) { > > + dev_err(pef2256->dev, "Only E1 line is currently supported\n"); > > + return -EOPNOTSUPP; > > + } > > + > > + return pef2256_setup_e1(pef2256); > > In order to use future addition of other modes, I'd do: > > if (!pef2256->is_e1) > return pef2256_setup_e1(pef2256); > > dev_err(pef2256->dev, "Only E1 line is currently supported\n"); > return -EOPNOTSUPP; > Will be changed in v3 using your proposition (with 'if' condition fixed). > > +} > > + > > + > > + > > +static void pef2256_isr_default_handler(struct pef2256 *pef2256, u8 nbr, u8 isr) > > +{ > > + dev_warn(pef2256->dev, "ISR%u: 0x%02x not handled\n", nbr, isr); > > +} > > + > > +static bool pef2256_is_carrier_on(struct pef2256 *pef2256) > > +{ > > + u8 frs0; > > + > > + frs0 = pef2256_read8(pef2256, PEF2256_FRS0); > > + return !(frs0 & (PEF2256_FRS0_LOS | PEF2256_FRS0_AIS)); > > +} > > + > > +static void pef2256_isr2_handler(struct pef2256 *pef2256, u8 nbr, u8 isr) > > +{ > > + bool is_changed = false; > > + unsigned long flags; > > + bool is_carrier_on; > > + > > + if (isr & (PEF2256_INT2_LOS | PEF2256_INT2_AIS)) { > > + > > + spin_lock_irqsave(&pef2256->lock, flags); > > + is_carrier_on = pef2256_is_carrier_on(pef2256); > > + if (is_carrier_on != pef2256->is_carrier_on) { > > + pef2256->is_carrier_on = is_carrier_on; > > + is_changed = true; > > + } > > + spin_unlock_irqrestore(&pef2256->lock, flags); > > Do we really need spin_locks for that ? > If atomicity is really an issue, may we use atomic operations instead ? Indeed, I can use atomic ops here. Will be changed in v3. > > > + > > + if (is_changed) > > + atomic_notifier_call_chain(&pef2256->event_notifier_list, > > + PEF2256_EVENT_CARRIER, NULL); > > + } > > +} > > + Thanks for the review. Regards, Hervé -- Hervé Codina, Bootlin Embedded Linux and Kernel engineering https://bootlin.com