summaryrefslogtreecommitdiff
path: root/src/soc/cavium/common/bdk-coreboot.c
blob: 740f8e442fe5ba6732ad1ded61bf9767426bc04e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 * This file is part of the coreboot project.
 *
 * Copyright 2017-present Facebook, Inc.
 * Copyright 2003-2017    Cavium Inc.  <support@cavium.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * This file consists of data imported from bdk-config.c
 */

// coreboot
#include <string.h>
#include <assert.h>
#include <device/i2c.h>
#include <device/i2c_simple.h>
#include <endian.h>
#include <soc/timer.h>

// BDK
#include <libbdk-arch/bdk-numa.h>
#include <libbdk-hal/bdk-config.h>
#include <libbdk-hal/bdk-twsi.h>
#include <libbdk-boot/bdk-watchdog.h>

/**
 * Do a twsi read from a 7 bit device address using an (optional)
 * internal address. Up to 4 bytes can be read at a time.
 *
 * @param twsi_id   which TWSI bus to use
 * @param dev_addr  Device address (7 bit)
 * @param internal_addr
 *		    Internal address.  Can be 0, 1 or 2 bytes in width
 * @param num_bytes Number of data bytes to read (1-4)
 * @param ia_width_bytes
 *		    Internal address size in bytes (0, 1, or 2)
 *
 * @return Read data, or -1 on failure
 */
int64_t bdk_twsix_read_ia(bdk_node_t node, int twsi_id, uint8_t dev_addr,
			  uint16_t internal_addr, int num_bytes,
			  int ia_width_bytes)
{
	struct i2c_msg seg[2];
	u32 buf;

	assert (num_bytes < 5);
	assert (ia_width_bytes < 3);

	seg[0].flags = 0;
	seg[0].slave = dev_addr;
	seg[0].buf   = (u8 *)&internal_addr;
	seg[0].len   = ia_width_bytes;
	seg[1].flags = I2C_M_RD;
	seg[1].slave = dev_addr;
	seg[1].buf   = (u8 *)&buf;
	seg[1].len   = num_bytes;

	if (i2c_transfer(twsi_id, seg, ARRAY_SIZE(seg)) < 0)
		return -1;

	return cpu_to_be32(buf);
}

/**
 * Write 1-8 bytes to a TWSI device using an internal address.
 *
 * @param twsi_id   which TWSI interface to use
 * @param dev_addr  TWSI device address (7 bit only)
 * @param internal_addr
 *		    TWSI internal address (0, 8, or 16 bits)
 * @param num_bytes Number of bytes to write (1-8)
 * @param ia_width_bytes
 *		    internal address width, in bytes (0, 1, 2)
 * @param data      Data to write.  Data is written MSB first on the twsi bus,
 *		    and only the lower num_bytes bytes of the argument are
 *		    valid.  If a 2 byte write is done, only the low 2 bytes of
 *		    the argument is used.
 *
 * @return Zero on success, -1 on error
 */
int bdk_twsix_write_ia(bdk_node_t node, int twsi_id, uint8_t dev_addr,
		       uint16_t internal_addr, int num_bytes,
		       int ia_width_bytes, uint64_t data)
{
	struct i2c_msg seg;
	u8 buf[10];

	assert (num_bytes <= 8);
	assert (ia_width_bytes < 3);

	memcpy(buf, &internal_addr, ia_width_bytes);
	memcpy(&buf[ia_width_bytes], &data, num_bytes);

	seg.flags = 0;
	seg.slave = dev_addr;
	seg.buf   = buf;
	seg.len   = num_bytes + ia_width_bytes;

	return platform_i2c_transfer(twsi_id, &seg, 1);
}

void bdk_watchdog_set(unsigned int timeout_ms)
{
	watchdog_set(0, timeout_ms);
}

void bdk_watchdog_poke(void)
{
	watchdog_poke(0);
}

void bdk_watchdog_disable(void)
{
	watchdog_disable(0);
}

int bdk_watchdog_is_running(void)
{
	return watchdog_is_running(0);
}