9090#define AT91_TWI_ACR_DATAL (len ) ((len) & 0xff)
9191#define AT91_TWI_ACR_DIR BIT(8)
9292
93+ #define AT91_TWI_FILTR 0x0044
94+ #define AT91_TWI_FILTR_FILT BIT(0)
95+ #define AT91_TWI_FILTR_PADFEN BIT(1)
96+ #define AT91_TWI_FILTR_PADFCFG BIT(2)
97+ #define AT91_TWI_FILTR_THRES (v ) ((v) << 8)
98+ #define AT91_TWI_FILTR_THRES_MASK GENMASK(10, 8)
99+
93100#define AT91_TWI_FMR 0x0050 /* FIFO Mode Register */
94101#define AT91_TWI_FMR_TXRDYM (mode ) (((mode) & 0x3) << 0)
95102#define AT91_TWI_FMR_TXRDYM_MASK (0x3 << 0)
@@ -114,6 +121,9 @@ struct at91_twi_pdata {
114121 bool has_unre_flag ;
115122 bool has_alt_cmd ;
116123 bool has_hold_field ;
124+ bool has_dig_filtr ;
125+ bool has_adv_dig_filtr ;
126+ bool has_ana_filtr ;
117127 struct at_dma_slave dma_slave ;
118128};
119129
@@ -146,6 +156,8 @@ struct at91_twi_dev {
146156 bool recv_len_abort ;
147157 u32 fifo_size ;
148158 struct at91_twi_dma dma ;
159+ bool enable_dig_filt ;
160+ bool enable_ana_filt ;
149161};
150162
151163static unsigned at91_twi_read (struct at91_twi_dev * dev , unsigned reg )
@@ -176,6 +188,9 @@ static void at91_twi_irq_restore(struct at91_twi_dev *dev)
176188
177189static void at91_init_twi_bus (struct at91_twi_dev * dev )
178190{
191+ struct at91_twi_pdata * pdata = dev -> pdata ;
192+ u32 filtr = 0 ;
193+
179194 at91_disable_twi_interrupts (dev );
180195 at91_twi_write (dev , AT91_TWI_CR , AT91_TWI_SWRST );
181196 /* FIFO should be enabled immediately after the software reset */
@@ -184,6 +199,22 @@ static void at91_init_twi_bus(struct at91_twi_dev *dev)
184199 at91_twi_write (dev , AT91_TWI_CR , AT91_TWI_MSEN );
185200 at91_twi_write (dev , AT91_TWI_CR , AT91_TWI_SVDIS );
186201 at91_twi_write (dev , AT91_TWI_CWGR , dev -> twi_cwgr_reg );
202+
203+ /* enable digital filter */
204+ if (pdata -> has_dig_filtr && dev -> enable_dig_filt )
205+ filtr |= AT91_TWI_FILTR_FILT ;
206+
207+ /* enable advanced digital filter */
208+ if (pdata -> has_adv_dig_filtr && dev -> enable_dig_filt )
209+ filtr |= AT91_TWI_FILTR_FILT |
210+ (AT91_TWI_FILTR_THRES (7 ) & AT91_TWI_FILTR_THRES_MASK );
211+
212+ /* enable analog filter */
213+ if (pdata -> has_ana_filtr && dev -> enable_ana_filt )
214+ filtr |= AT91_TWI_FILTR_PADFEN | AT91_TWI_FILTR_PADFCFG ;
215+
216+ if (filtr )
217+ at91_twi_write (dev , AT91_TWI_FILTR , filtr );
187218}
188219
189220/*
@@ -831,6 +862,9 @@ static struct at91_twi_pdata at91rm9200_config = {
831862 .has_unre_flag = true,
832863 .has_alt_cmd = false,
833864 .has_hold_field = false,
865+ .has_dig_filtr = false,
866+ .has_adv_dig_filtr = false,
867+ .has_ana_filtr = false,
834868};
835869
836870static struct at91_twi_pdata at91sam9261_config = {
@@ -839,6 +873,9 @@ static struct at91_twi_pdata at91sam9261_config = {
839873 .has_unre_flag = false,
840874 .has_alt_cmd = false,
841875 .has_hold_field = false,
876+ .has_dig_filtr = false,
877+ .has_adv_dig_filtr = false,
878+ .has_ana_filtr = false,
842879};
843880
844881static struct at91_twi_pdata at91sam9260_config = {
@@ -847,6 +884,9 @@ static struct at91_twi_pdata at91sam9260_config = {
847884 .has_unre_flag = false,
848885 .has_alt_cmd = false,
849886 .has_hold_field = false,
887+ .has_dig_filtr = false,
888+ .has_adv_dig_filtr = false,
889+ .has_ana_filtr = false,
850890};
851891
852892static struct at91_twi_pdata at91sam9g20_config = {
@@ -855,6 +895,9 @@ static struct at91_twi_pdata at91sam9g20_config = {
855895 .has_unre_flag = false,
856896 .has_alt_cmd = false,
857897 .has_hold_field = false,
898+ .has_dig_filtr = false,
899+ .has_adv_dig_filtr = false,
900+ .has_ana_filtr = false,
858901};
859902
860903static struct at91_twi_pdata at91sam9g10_config = {
@@ -863,6 +906,9 @@ static struct at91_twi_pdata at91sam9g10_config = {
863906 .has_unre_flag = false,
864907 .has_alt_cmd = false,
865908 .has_hold_field = false,
909+ .has_dig_filtr = false,
910+ .has_adv_dig_filtr = false,
911+ .has_ana_filtr = false,
866912};
867913
868914static const struct platform_device_id at91_twi_devtypes [] = {
@@ -893,6 +939,9 @@ static struct at91_twi_pdata at91sam9x5_config = {
893939 .has_unre_flag = false,
894940 .has_alt_cmd = false,
895941 .has_hold_field = false,
942+ .has_dig_filtr = false,
943+ .has_adv_dig_filtr = false,
944+ .has_ana_filtr = false,
896945};
897946
898947static struct at91_twi_pdata sama5d4_config = {
@@ -901,6 +950,9 @@ static struct at91_twi_pdata sama5d4_config = {
901950 .has_unre_flag = false,
902951 .has_alt_cmd = false,
903952 .has_hold_field = true,
953+ .has_dig_filtr = true,
954+ .has_adv_dig_filtr = false,
955+ .has_ana_filtr = false,
904956};
905957
906958static struct at91_twi_pdata sama5d2_config = {
@@ -909,6 +961,20 @@ static struct at91_twi_pdata sama5d2_config = {
909961 .has_unre_flag = true,
910962 .has_alt_cmd = true,
911963 .has_hold_field = true,
964+ .has_dig_filtr = true,
965+ .has_adv_dig_filtr = true,
966+ .has_ana_filtr = true,
967+ };
968+
969+ static struct at91_twi_pdata sam9x60_config = {
970+ .clk_max_div = 7 ,
971+ .clk_offset = 4 ,
972+ .has_unre_flag = true,
973+ .has_alt_cmd = true,
974+ .has_hold_field = true,
975+ .has_dig_filtr = true,
976+ .has_adv_dig_filtr = true,
977+ .has_ana_filtr = true,
912978};
913979
914980static const struct of_device_id atmel_twi_dt_ids [] = {
@@ -936,6 +1002,9 @@ static const struct of_device_id atmel_twi_dt_ids[] = {
9361002 }, {
9371003 .compatible = "atmel,sama5d2-i2c" ,
9381004 .data = & sama5d2_config ,
1005+ }, {
1006+ .compatible = "microchip,sam9x60-i2c" ,
1007+ .data = & sam9x60_config ,
9391008 }, {
9401009 /* sentinel */
9411010 }
@@ -1105,6 +1174,12 @@ static int at91_twi_probe(struct platform_device *pdev)
11051174 if (rc )
11061175 bus_clk_rate = DEFAULT_TWI_CLK_HZ ;
11071176
1177+ dev -> enable_dig_filt = of_property_read_bool (pdev -> dev .of_node ,
1178+ "enable-dig-filt" );
1179+
1180+ dev -> enable_ana_filt = of_property_read_bool (pdev -> dev .of_node ,
1181+ "enable-ana-filt" );
1182+
11081183 at91_calc_twi_clock (dev , bus_clk_rate );
11091184 at91_init_twi_bus (dev );
11101185
0 commit comments