1+ /**
2+ * @file bmp280.c
3+ * @author IotaHydrae (writeforever@foxmail.com)
4+ * @brief
5+ * @version 0.1
6+ * @date 2023-03-14
7+ *
8+ * MIT License
9+ *
10+ * Copyright 2022 IotaHydrae(writeforever@foxmail.com)
11+ *
12+ * Permission is hereby granted, free of charge, to any person obtaining a copy
13+ * of this software and associated documentation files (the "Software"), to deal
14+ * in the Software without restriction, including without limitation the rights
15+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16+ * copies of the Software, and to permit persons to whom the Software is
17+ * furnished to do so, subject to the following conditions:
18+ *
19+ * The above copyright notice and this permission notice shall be included in all
20+ * copies or substantial portions of the Software.
21+ *
22+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28+ *
29+ */
30+
31+ #include "common/init.h"
32+ #include "common/tools.h"
33+ #include "common/bitops.h"
34+
35+ #include "i2c/native_i2c.h"
36+
37+ #define BMP280_ADDR 0x76
38+
39+ #define BMP280_ID 0x58
40+
41+ #define BMP280_REG_ID 0xD0
42+ #define BMP280_REG_RESET 0xE0
43+
44+ #define BMP280_CMD_STATUS 0xF3
45+ #define BMP280_STATUS_MEASURING BIT(3)
46+ #define BMP280_STATUS_IM_UPDATE BIT(0)
47+
48+ #define BMP280_REG_CTRL_MEAS 0xF4
49+
50+ #define BMP280_REG_CONFIG 0xF5
51+
52+ #define BMP280_CMD_PRESS_MSB 0xF7
53+ #define BMP280_CMD_PRESS_LSB 0xF8
54+ #define BMP280_CMD_PRESS_XLSB 0xF9
55+
56+ #define BMP280_CMD_TEMP_MSB 0xFA
57+ #define BMP280_CMD_TEMP_LSB 0xFB
58+ #define BMP280_CMD_TEMP_XLSB 0xFC
59+
60+ #define DRV_NAME "bmp280"
61+
62+ enum bmp280_power_mode {
63+ BMP280_PWR_MODE_SLEEP = 0x00 ,
64+ BMP280_PWR_MODE_FORCED = 0x01 ,
65+ BMP280_PWR_MODE_NORMAL = 0x03 ,
66+ };
67+
68+ struct bmp280_data {
69+ /* usually fixed value, read once */
70+ u16 dig_T1 ;
71+ s16 dig_T2 , dig_T3 ;
72+
73+ s32 var1 , var2 , t_fine ;
74+
75+ s32 adc_T ;
76+ u8 msb , lsb , xlsb ;
77+ };
78+
79+ struct bmp280_config {
80+ /* in register 0xf4 `ctrl_meas` */
81+ u8 osrs_t ;
82+ u8 osrs_p ;
83+ u8 pwr_mode ; /* working mode */
84+
85+ /* in register 0xf5 `config` */
86+ u8 t_sb ;
87+ u8 filter ;
88+ u8 spi3w_en ;
89+ };
90+
91+ struct bmp280 {
92+ int id ; /* used to specifiy which kind of variant */
93+
94+ s32 pressure ; /* the result of pressure */
95+ s32 temperature ; /* the result of temperature */
96+
97+ struct bmp280_config cfg ;
98+ struct bmp280_data raw ; /* the raw data reading from sensor */
99+ };
100+
101+ int bmp280_read_id (void )
102+ {
103+ int id = i2c_read_reg (BMP280_ADDR , BMP280_REG_ID );
104+ pr_debug ("id : 0x%02x\n" , id );
105+ if (id == BMP280_ID ) {
106+ pr_debug ("device : bmp280 detected!\n" );
107+ return id ;
108+ }
109+
110+ return 0 ;
111+ }
112+
113+ int bmp280_read_press (void )
114+ {
115+ u8 msb , lsb , xlsb ;
116+ u16 press ;
117+
118+ msb = i2c_read_reg (BMP280_ADDR , BMP280_CMD_PRESS_MSB );
119+ lsb = i2c_read_reg (BMP280_ADDR , BMP280_CMD_PRESS_LSB );
120+
121+ press = msb << 8 | lsb ;
122+
123+ pr_debug ("press : %d\n" , press );
124+ return press ;
125+ }
126+
127+ s32 bmp280_read_temp (void )
128+ {
129+ s32 var1 , var2 , adc_T , t_fine , T ;
130+ u16 dig_T1 ;
131+ s16 dig_T2 , dig_T3 ;
132+ u8 msb , lsb , xlsb ;
133+
134+ dig_T1 = i2c_read_reg (BMP280_ADDR , 0x89 ) << 8 | i2c_read_reg (BMP280_ADDR , 0x88 );
135+ dig_T2 = i2c_read_reg (BMP280_ADDR , 0x8B ) << 8 | i2c_read_reg (BMP280_ADDR , 0x8A );
136+ dig_T3 = i2c_read_reg (BMP280_ADDR , 0x8F ) << 8 | i2c_read_reg (BMP280_ADDR , 0x8E );
137+
138+ msb = i2c_read_reg (BMP280_ADDR , BMP280_CMD_TEMP_MSB );
139+ lsb = i2c_read_reg (BMP280_ADDR , BMP280_CMD_TEMP_LSB );
140+ xlsb = i2c_read_reg (BMP280_ADDR , BMP280_CMD_TEMP_XLSB ) >> 4 ;
141+
142+ adc_T = msb << 12 | lsb << 4 | xlsb ;
143+
144+ /* calcualting */
145+ // var1 = ((double)adc_T)/16384.0 - ((double)dig_T1/1024.0) * ((double)dig_T2);
146+ // var2 = ((double)adc_T)/31072.0 - (((double)dig_T1)/8192.0) * (((double)adc_T)/131072.0) - (((double)dig_T1)/8192.0) * ((double)dig_T3);
147+ var1 = ((((adc_T >> 3 ) - ((s32 )dig_T1 << 1 ))) * ((s32 )dig_T2 )) >> 11 ;
148+ var2 = (((((adc_T >> 4 ) - ((s32 )dig_T1 )) * ((adc_T >> 4 ) - ((s32 )dig_T1 ))) >> 12 ) *
149+ ((s32 )dig_T3 )) >> 14 ;
150+ t_fine = var1 + var2 ;
151+
152+ /* format etc. 2516 -> 25.16 °C */
153+ T = (t_fine * 5 + 128 ) >> 8 ;
154+
155+ pr_debug (" Temp : %d.%d *C\n" , T / 100 , T % 100 );
156+
157+ return T ;
158+ }
159+
160+ static void bmp280_hw_init (void )
161+ {
162+ /* power-on reset */
163+ i2c_write_reg (BMP280_ADDR , BMP280_REG_RESET , 0xB6 );
164+
165+ /* eanble measurements, set work mode to normal */
166+ u8 ctrl_meas = BIT (5 ) | BIT (2 ) | 3 ;
167+ i2c_write_reg (BMP280_ADDR , BMP280_REG_CTRL_MEAS , ctrl_meas );
168+ }
169+
170+ static int bmp280_drv_init (void )
171+ {
172+ bmp280_hw_init ();
173+ }
174+
175+ static int bmp280_drv_exit (void )
176+ {
177+
178+ }
179+
180+ device_initcall (bmp280_drv_init );
181+ device_initcall (bmp280_drv_exit );
0 commit comments