[Skiboot] [PATCH 2/2] dts: add DIMM temperature sensors

Benjamin Herrenschmidt benh at au1.ibm.com
Tue Jun 23 08:07:17 AEST 2015


On Mon, 2015-06-22 at 13:53 +0200, Cédric Le Goater wrote:
> The DIMM temperatures are stored in the Centaur's sensor cache. This 
> patch adds the necessary interface to read theses values and expose
> them to the host OS through the sensor framework of OPAL.

So you are reading the cache via SCOMs to the Centaur. Isn't the cache
also readable on the PowerBus using MMIOs ? AFAIK that's the path the
OCC takes no ?

> Signed-off-by: Cédric Le Goater <clg at fr.ibm.com>
> ---
>  hw/dts.c |  149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 149 insertions(+)
> 
> Index: skiboot.git/hw/dts.c
> ===================================================================
> --- skiboot.git.orig/hw/dts.c
> +++ skiboot.git/hw/dts.c
> @@ -42,6 +42,7 @@ struct dts {
>  	uint8_t		valid;
>  	uint8_t		trip;
>  	int16_t		temp;
> +	int8_t		status;
>  };
>  
>  /* Different sensor locations */
> @@ -209,6 +210,98 @@ static int dts_read_core_temp(uint32_t p
>  	return rc;
>  }
>  
> +/*
> + * Centaur Sensor Cache Registers
> + */
> +#define CENTAUR_SCAC_DATA0_3	0x020115CA
> +#define CENTAUR_SCAC_DATA4_7	0x020115CB
> +#define CENTAUR_SCAC_ENABLE	0x020115CC
> +#define CENTAUR_SCAC_LFIR	0x020115C0
> +
> +enum centaur_scac_status {
> +	SCAC_STATUS_STALLED_OR_DISABLED	= 0x0, /* should check LFIR */
> +	SCAC_STATUS_ERROR		= 0x1, /* should check LFIR */
> +	SCAC_STATUS_VALID_READING	= 0x2,
> +	SCAC_STATUS_VALID_READING_NEW	= 0x3  /* First read */
> +};
> +
> +/*
> + * 0		Critical Trip Alarm
> + * 1		Above Window Alarm
> + * 2		Below Window Alarm
> + * 3		Temperature Sign Bit
> + * [4:13]	Temperature = A(4:11) + B(12:13) (Celsius)
> + * [14:15]	Status Indicator (see enum centaur_scac_status)
> + */
> +static void dts_decode_one_dimm_dts(uint16_t raw, struct dts *dts)
> +{
> +	uint8_t sign;
> +
> +	dts->status = raw & 0x3;
> +	dts->valid  = raw & 0x2;
> +	dts->temp   = ((raw >> 4) & 0xff) + ((raw >> 2) & 0x3);
> +	dts->trip   = (raw >> 13) & 0x7;
> +
> +	sign = (raw >> 12) & 0x1;
> +	if (sign)
> +		dts->temp *= -1;
> +}
> +
> +#define MAX_DIMMS 8
> +
> +static const uint64_t scac_data_addrs[MAX_DIMMS] = {
> +	[0 ... 3] = CENTAUR_SCAC_DATA0_3,
> +	[4 ... 7] = CENTAUR_SCAC_DATA4_7
> +};
> +
> +static int dts_read_dimm_temp(uint32_t chip_id, uint8_t dimm_id,
> +			      struct dts *dts)
> +{
> +	uint64_t data;
> +	uint64_t enable;
> +	int rc;
> +	struct dts temps[4];
> +
> +	if (dimm_id >= MAX_DIMMS) {
> +		prerror("DTS: Chip %x Dimm %x does not exist\n", chip_id,
> +		       dimm_id);
> +		return OPAL_PARAMETER;
> +	}
> +
> +	rc = xscom_read(chip_id, CENTAUR_SCAC_ENABLE, &enable);
> +	if (rc)
> +		return rc;
> +
> +	if (!(enable & PPC_BIT(dimm_id))) {
> +		prerror("DTS: Chip %x Dimm %x is disabled\n", chip_id,
> +		       dimm_id);
> +		return OPAL_RESOURCE;
> +	}
> +
> +	rc = xscom_read(chip_id, scac_data_addrs[dimm_id], &data);
> +	if (rc)
> +		return rc;
> +
> +	dts_decode_one_dimm_dts(data >> 48, &temps[0]);
> +	dts_decode_one_dimm_dts(data >> 32, &temps[1]);
> +	dts_decode_one_dimm_dts(data >> 16, &temps[2]);
> +	dts_decode_one_dimm_dts(data >> 0,  &temps[3]);
> +
> +	memcpy(dts, &temps[dimm_id % 4], sizeof(*dts));
> +
> +	if (!dts->valid) {
> +		uint64_t lfir;
> +
> +		xscom_read(chip_id, CENTAUR_SCAC_LFIR, &lfir);
> +		prerror("DTS: Chip %x Dimm %x invalid status:%x fir:%016llx\n",
> +			chip_id, dimm_id, dts->status, lfir);
> +		return OPAL_HARDWARE;
> +	}
> +
> +	prlog(PR_TRACE, "DTS: Chip %x Dimm %x temp:%dC trip:%x status:%x\n",
> +	      chip_id, dimm_id, dts->temp, dts->trip, dts->status);
> +	return 0;
> +}
>  
>  /* Different sensor locations */
>  #define P8_MEM_DTS0	0
> @@ -261,6 +354,7 @@ static int dts_read_mem_temp(uint32_t ch
>  enum sensor_dts_class {
>  	SENSOR_DTS_CORE_TEMP,
>  	SENSOR_DTS_MEM_TEMP,
> +	SENSOR_DTS_DIMM_TEMP,
>  	/* To be continued */
>  };
>  
> @@ -277,6 +371,7 @@ enum {
>   * resource identifier field of the sensor handler
>   */
>  #define centaur_get_id(rid) (0x80000000 | ((rid) & 0x3ff))
> +#define dimm_get_id(rid) ((rid) >> 10)
>  
>  int64_t dts_sensor_read(uint32_t sensor_hndl, uint32_t *sensor_data)
>  {
> @@ -297,6 +392,10 @@ int64_t dts_sensor_read(uint32_t sensor_
>  	case SENSOR_DTS_MEM_TEMP:
>  		rc = dts_read_mem_temp(centaur_get_id(rid), &dts);
>  		break;
> +	case SENSOR_DTS_DIMM_TEMP:
> +		rc = dts_read_dimm_temp(centaur_get_id(rid), dimm_get_id(rid),
> +					&dts);
> +		break;
>  	default:
>  		rc = OPAL_PARAMETER;
>  		break;
> @@ -333,11 +432,16 @@ int64_t dts_sensor_read(uint32_t sensor_
>  	sensor_make_handler(SENSOR_DTS_MEM_TEMP|SENSOR_DTS,		\
>  			    centaur_make_id(chip_id, 0), attr_id)
>  
> +#define dimm_handler(cen_id, dimm_id, attr_id)				\
> +	sensor_make_handler(SENSOR_DTS_DIMM_TEMP|SENSOR_DTS,		\
> +			    centaur_make_id(chip_id, i), attr_id)
> +
>  bool dts_sensor_create_nodes(struct dt_node *sensors)
>  {
>  	struct proc_chip *chip;
>  	struct dt_node *cn;
>  	char name[64];
> +	int dimm_num = 1;
>  
>  	/* build the device tree nodes :
>  	 *
> @@ -375,6 +479,9 @@ bool dts_sensor_create_nodes(struct dt_n
>  		uint32_t chip_id;
>  		struct dt_node *node;
>  		uint32_t handler;
> +		uint64_t enable;
> +		int rc;
> +		int i;
>  
>  		chip_id = dt_prop_get_u32(cn, "ibm,chip-id");
>  
> @@ -391,6 +498,48 @@ bool dts_sensor_create_nodes(struct dt_n
>  		dt_add_property_string(node, "sensor-type", "temp");
>  		dt_add_property_cells(node, "ibm,chip-id", chip_id);
>  		dt_add_property_string(node, "label", "Centaur");
> +
> +		rc = xscom_read(chip_id, CENTAUR_SCAC_ENABLE, &enable);
> +		if (rc) {
> +			prerror("DTS: Chip %x failed to create nodes for DIMMs",
> +			       chip_id);
> +			continue;
> +		}
> +
> +		for (i = 0; i < MAX_DIMMS; i++, dimm_num++) {
> +			if (!(enable & PPC_BIT(i))) {
> +				prlog(PR_INFO, "DTS: Chip %x Dimm %x is disabled\n",
> +					chip_id, i);
> +				continue;
> +			}
> +
> +			snprintf(name, sizeof(name), "dimm-temp@%x-%x",
> +				 chip_id, i);
> +
> +			/*
> +			 * We only have two bytes for the resource
> +			 * identifier. Let's trunctate the centaur chip id
> +			 */
> +			handler = dimm_handler(chip_id, i,
> +					       SENSOR_DTS_ATTR_TEMP_MAX);
> +			node = dt_new(sensors, name);
> +			dt_add_property_string(node, "compatible",
> +					       "ibm,opal-sensor");
> +			dt_add_property_cells(node, "sensor-data", handler);
> +
> +			handler = dimm_handler(chip_id, i,
> +					       SENSOR_DTS_ATTR_TEMP_TRIP);
> +			dt_add_property_cells(node, "sensor-status", handler);
> +			dt_add_property_string(node, "sensor-type", "temp");
> +
> +			/*
> +			 *  Use a global increment for the DIMMs. It
> +			 *  gives a quick idea on how slots are
> +			 *  populated on the system.
> +			 */
> +			snprintf(name, sizeof(name), "Dimm %d", dimm_num);
> +			dt_add_property_string(node, "label", name);
> +		}
>  	}
>  
>  	return true;
> 
> _______________________________________________
> Skiboot mailing list
> Skiboot at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot




More information about the Skiboot mailing list